From 093676c1740888e1c7358fc2847450b8d4ce1fb1 Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Fri, 30 Oct 2026 17:16:27 -0400 Subject: [PATCH 1/4] chore: upgrade eve to 1.0.0-rc.0 Signed-off-by: Colton Padden --- app/_components/agent-chat.tsx | 37 +- app/_components/agent-message.tsx | 75 +- components/ai-elements/tool.tsx | 63 +- package.json | 10 +- pnpm-lock.yaml | 6384 +++++++++++++++++++++++++++++ pnpm-workspace.yaml | 2 + 6 files changed, 6476 insertions(+), 95 deletions(-) create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml diff --git a/app/_components/agent-chat.tsx b/app/_components/agent-chat.tsx index 172a295..61a5342 100644 --- a/app/_components/agent-chat.tsx +++ b/app/_components/agent-chat.tsx @@ -43,7 +43,7 @@ function extractLiveUrl(messages: readonly EveMessage[]): string | null { let found: string | null = null; for (const message of messages) { for (const part of message.parts) { - if (part.type !== "dynamic-tool" || part.toolName !== "open_cloud_browser") continue; + if (part.type !== "tool" || part.name !== "open_cloud_browser") continue; const out = part.output; let url: unknown; if (out && typeof out === "object" && "liveUrl" in out) { @@ -59,21 +59,26 @@ function extractLiveUrl(messages: readonly EveMessage[]): string | null { export function AgentChat() { const agent = useEveAgent(); - const isBusy = agent.status === "submitted" || agent.status === "streaming"; - const isEmpty = agent.data.messages.length === 0; - const liveUrl = extractLiveUrl(agent.data.messages); + const isBusy = agent.status === "busy"; + const isEmpty = agent.messages.length === 0; + const liveUrl = extractLiveUrl(agent.messages); const handleSubmit = async (message: PromptInputMessage) => { const text = message.text.trim(); if (!text || isBusy) return; - await agent.send({ message: text }); + await agent.send(text); }; const composer = ( - + { + void agent.cancel(); + }} + status={isBusy ? "streaming" : "ready"} + /> ); @@ -112,15 +117,17 @@ export function AgentChat() { {isEmpty ? null : ( - {agent.data.messages.map((message, index) => ( + {agent.messages.map((message, index) => ( agent.send({ inputResponses })} + onAnswers={async (answers) => { + await agent.respond(answers); + }} /> ))} @@ -158,15 +165,9 @@ export function AgentChat() { } function StatusDot({ status }: { readonly status: AgentStatus }) { - const isLive = status === "submitted" || status === "streaming"; + const isLive = status === "busy"; const tone = - status === "error" - ? "bg-destructive" - : isLive - ? "bg-emerald-500" - : status === "ready" - ? "bg-muted-foreground" - : "bg-muted-foreground/50"; + isLive ? "bg-emerald-500" : status === "idle" ? "bg-muted-foreground" : "bg-muted-foreground/50"; return ( diff --git a/app/_components/agent-message.tsx b/app/_components/agent-message.tsx index adfd6bc..52fb668 100644 --- a/app/_components/agent-message.tsx +++ b/app/_components/agent-message.tsx @@ -1,6 +1,6 @@ "use client"; -import type { EveDynamicToolPart, EveMessage, EveMessagePart } from "eve/react"; +import type { EveInteractionPart, EveMessage, EveMessagePart, EveToolPart } from "eve/react"; import { Message, MessageContent, MessageResponse } from "@/components/ai-elements/message"; import { Reasoning, ReasoningContent, ReasoningTrigger } from "@/components/ai-elements/reasoning"; import { @@ -12,9 +12,9 @@ import { } from "@/components/ai-elements/tool"; import { Button } from "@/components/ui/button"; -export type AgentInputResponse = { +export type AgentAnswer = { readonly optionId?: string; - readonly requestId: string; + readonly interactionId: string; readonly text?: string; }; @@ -22,12 +22,12 @@ export function AgentMessage({ canRespond, isStreaming, message, - onInputResponses, + onAnswers, }: { readonly canRespond: boolean; readonly isStreaming: boolean; readonly message: EveMessage; - readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise; + readonly onAnswers: (answers: readonly AgentAnswer[]) => void | Promise; }) { const lastTextIndex = message.parts.reduce( (last, part, index) => (part.type === "text" ? index : last), @@ -44,7 +44,7 @@ export function AgentMessage({ @@ -56,18 +56,16 @@ export function AgentMessage({ function AgentMessagePart({ canRespond, - onInputResponses, + onAnswers, part, showCaret, }: { readonly canRespond: boolean; - readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise; + readonly onAnswers: (answers: readonly AgentAnswer[]) => void | Promise; readonly part: EveMessagePart; readonly showCaret: boolean; }) { switch (part.type) { - case "step-start": - return null; case "text": return ( @@ -81,68 +79,67 @@ function AgentMessagePart({ {part.text} ); - case "dynamic-tool": + case "tool": return ( - + - - } + - + ); + case "interaction": + return ; } } -function InputRequestActions({ +function InteractionActions({ canRespond, - onInputResponses, + onAnswers, part, }: { readonly canRespond: boolean; - readonly onInputResponses: (responses: readonly AgentInputResponse[]) => void | Promise; - readonly part: EveDynamicToolPart; + readonly onAnswers: (answers: readonly AgentAnswer[]) => void | Promise; + readonly part: EveToolPart | EveInteractionPart; }) { - const inputRequest = part.toolMetadata?.eve?.inputRequest; - if (!inputRequest) { + const interaction = part.type === "tool" ? part.interaction : part; + if (!interaction || interaction.request.kind === "sign-in") { return null; } - const inputResponse = part.toolMetadata?.eve?.inputResponse; - const selectedOption = inputRequest.options?.find( - (option) => option.id === inputResponse?.optionId, + const selectedOption = interaction.request.options?.find( + (option) => option.id === interaction.answer?.optionId, ); return (
-

{inputRequest.prompt}

- {inputResponse ? ( +

{interaction.request.prompt}

+ {interaction.answer ? (

- Responded: {selectedOption?.label ?? inputResponse.text ?? inputResponse.optionId} + Responded: {selectedOption?.label ?? interaction.answer.text ?? interaction.answer.optionId}

) : (
- {inputRequest.options?.map((option) => ( + {interaction.request.options?.map((option) => (
- )} + ) : null} +
+ ); +} + +function FreeTextAnswer({ + canRespond, + interactionId, + onAnswers, +}: { + readonly canRespond: boolean; + readonly interactionId: string; + readonly onAnswers: (answers: readonly AgentAnswer[]) => void | Promise; +}) { + const [text, setText] = useState(""); + + const submit = (event: FormEvent) => { + event.preventDefault(); + const answer = text.trim(); + if (!answer || !canRespond) return; + void onAnswers([{ interactionId, text: answer }]); + }; + + return ( +
+ setText(event.currentTarget.value)} + placeholder="Type your answer…" + value={text} + /> + +
+ ); +} + +function SignInPrompt({ + interaction, +}: { + readonly interaction: EveInteractionPart | NonNullable; +}) { + const signIn = interaction.request.signIn; + const name = signIn?.displayName ?? signIn?.name ?? "the service"; + const settled = interaction.status === "settled"; + + return ( +
+

+ {settled ? `${name} authorization ${signInEnding(interaction.outcome ?? "withdrawn")}` : `Connect ${name}`} +

+

+ {settled ? interaction.reason ?? "The sign-in request has finished." : signIn?.instructions ?? interaction.request.prompt} +

+ {!settled && signIn?.userCode ? ( +

+ Code: {signIn.userCode} +

+ ) : null} + {!settled && signIn?.url ? ( + + ) : null}
); } From 7dce56bde4f3d881d487052feea504d097e7483b Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Fri, 30 Oct 2026 17:35:51 -0400 Subject: [PATCH 3/4] docs: clarify Eve 1 release prerequisite Signed-off-by: Colton Padden --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a84e4d1..39124d3 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,13 @@ It's a single Next.js service: `withEve()` in [`next.config.ts`](next.config.ts) ## Quick Start +> **Eve 1 release prerequisite:** This migration intentionally keeps the +> `@browser_use/eve` browser extension and its normal peer-dependency validation. +> The currently pinned `0.0.4` release declares `eve <1`, so a clean npm install +> remains blocked until Browser Use publishes an Eve 1-compatible extension release. +> Do not remove the plugin or install with peer-dependency bypass flags; upgrade the +> extension when that release is available. + ### Deploy to Vercel [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fbrowser-use%2Fbrowser-agent-template&env=BROWSER_USE_API_KEY,AI_GATEWAY_API_KEY&envDescription=BROWSER_USE_API_KEY%20from%20browser-use.com%20%7C%20a%20model%20credential%20for%20the%20AI%20Gateway&envLink=https%3A%2F%2Fgithub.com%2Fbrowser-use%2Fbrowser-agent-template%2Fblob%2Fmain%2Fdocs%2FENVIRONMENT.md&project-name=browser-agent&repository-name=browser-agent) @@ -75,13 +82,6 @@ cp .env.example .env.local npm run dev ``` -> **Eve 1 release prerequisite:** This migration intentionally keeps the -> `@browser_use/eve` browser extension and its normal peer-dependency validation. -> The currently pinned `0.0.4` release declares `eve <1`, so a clean npm install -> remains blocked until Browser Use publishes an Eve 1-compatible extension release. -> Do not remove the plugin or install with peer-dependency bypass flags; upgrade the -> extension when that release is available. - Open [http://localhost:3000](http://localhost:3000) and ask: _"Go to news.ycombinator.com and give me the top 5 posts."_ **Required environment variables:** From 869a19d97ee3a301783ef568e40dfe1f58e6edd3 Mon Sep 17 00:00:00 2001 From: Colton Padden Date: Mon, 2 Nov 2026 11:25:28 -0500 Subject: [PATCH 4/4] chore: update eve to 1.0.0-rc.1 and Connect to 2.7.0 Signed-off-by: Colton Padden --- package.json | 4 ++-- pnpm-lock.yaml | 34 +++++++++++++++++----------------- pnpm-workspace.yaml | 3 ++- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 9a9e839..f8a6060 100644 --- a/package.json +++ b/package.json @@ -23,12 +23,12 @@ "@streamdown/math": "1.0.2", "@streamdown/mermaid": "1.0.2", "@tailwindcss/postcss": "4.3.0", - "@vercel/connect": "2.6.0", + "@vercel/connect": "2.7.0", "ai": "7.0.158", "class-variance-authority": "0.7.1", "clsx": "2.1.1", "cmdk": "1.1.1", - "eve": "^1.0.0-rc.0", + "eve": "^1.0.0-rc.1", "lucide-react": "1.16.0", "motion": "12.40.0", "nanoid": "5.1.16", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6872c51..223b0af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@browser_use/eve': specifier: ^0.0.4 - version: 0.0.4(eve@1.0.0-rc.0)(zod@4.4.3) + version: 0.0.4(eve@1.0.0-rc.1)(zod@4.4.3) '@radix-ui/react-use-controllable-state': specifier: 1.2.2 version: 1.2.2(@types/react@19.2.15)(react@19.2.6) @@ -39,8 +39,8 @@ importers: specifier: 4.3.0 version: 4.3.0 '@vercel/connect': - specifier: 2.6.0 - version: 2.6.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.0) + specifier: 2.7.0 + version: 2.7.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.1) ai: specifier: 7.0.158 version: 7.0.158(zod@4.4.3) @@ -54,8 +54,8 @@ importers: specifier: 1.1.1 version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.15))(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) eve: - specifier: ^1.0.0-rc.0 - version: 1.0.0-rc.0(@vercel/connect@2.6.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + specifier: ^1.0.0-rc.1 + version: 1.0.0-rc.1(@vercel/connect@2.7.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) lucide-react: specifier: 1.16.0 version: 1.16.0(react@19.2.6) @@ -1749,8 +1749,8 @@ packages: resolution: {integrity: sha512-g9XerViJ/paZujufXYcu5XYI2vU2rtB4sgdpjUHde5RnOkdmpu0ngH46LCFGHoPXO/C+qDPSczIHIRN+8Q2YKQ==} engines: {node: '>= 18'} - '@vercel/connect@2.6.0': - resolution: {integrity: sha512-7fh5WT1djgda/tN4vlQlvfcaVtHuqOn91lDjExp6Gvaax+/4761l8nkvWcMAkjZ1KWl4NDz3Cm2yMHwv5CSahw==} + '@vercel/connect@2.7.0': + resolution: {integrity: sha512-kwg83Oo2LLYeFZnMuOI/OtRaJNNuSw6sR3ChdKBk2heKRMmach54ElGAxFrDoE+pfT9eIGVdjU3ct0GaoHF9Vw==} peerDependencies: '@ai-sdk/mcp': ^1 || ^2 '@auth/core': '>=0.41.3' @@ -1758,7 +1758,7 @@ packages: '@modelcontextprotocol/sdk': ^1.29.0 ai: ^6 || ^7.0.0-beta.0 better-auth: '>=1.5.0' - eve: '>=0.39.1' + eve: '>=0.39.1 || >=1.0.0-0' peerDependenciesMeta: '@ai-sdk/mcp': optional: true @@ -2108,8 +2108,8 @@ packages: estree-util-is-identifier-name@3.0.0: resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - eve@1.0.0-rc.0: - resolution: {integrity: sha512-/GOeOMIgoohAP7xpTqOxrWO8H6Miiv6UN2dA04R+40RN9rpXoLQ4JEdqd5G4dyeEc2Ou6zK5krwcZOHfgpOObA==} + eve@1.0.0-rc.1: + resolution: {integrity: sha512-yg1zd3Wwi0OY+ue6NP8IV3gPa+Kth9jIB6Af0/sqVElySXWKxL9j0lNkTAddTI38SbyEu0Z11YCZhIlaOQTZLQ==} engines: {node: '>=24'} hasBin: true peerDependencies: @@ -2117,7 +2117,7 @@ packages: '@nuxt/kit': ^4.0.0 '@nuxt/schema': ^4.0.0 '@opentelemetry/api': ^1.0.0 - '@vercel/connect': ^2.5.2 + '@vercel/connect': ^2.7.0 ai: ^7.0.137 braintrust: ^3.0.0 chat: ^4.42.0 @@ -3145,10 +3145,10 @@ snapshots: '@braintree/sanitize-url@7.1.2': {} - '@browser_use/eve@0.0.4(eve@1.0.0-rc.0)(zod@4.4.3)': + '@browser_use/eve@0.0.4(eve@1.0.0-rc.1)(zod@4.4.3)': dependencies: browser-use-sdk: 3.12.1 - eve: 1.0.0-rc.0(@vercel/connect@2.6.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + eve: 1.0.0-rc.1(@vercel/connect@2.7.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) zod: 4.4.3 transitivePeerDependencies: - '@x402/evm' @@ -4671,12 +4671,12 @@ snapshots: dependencies: execa: 5.1.1 - '@vercel/connect@2.6.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.0)': + '@vercel/connect@2.7.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.1)': dependencies: '@vercel/oidc': 4.0.5 optionalDependencies: ai: 7.0.158(zod@4.4.3) - eve: 1.0.0-rc.0(@vercel/connect@2.6.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + eve: 1.0.0-rc.1(@vercel/connect@2.7.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) '@vercel/oidc@3.2.0': {} @@ -5004,13 +5004,13 @@ snapshots: estree-util-is-identifier-name@3.0.0: {} - eve@1.0.0-rc.0(@vercel/connect@2.6.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6): + eve@1.0.0-rc.1(@vercel/connect@2.7.0)(ai@7.0.158(zod@4.4.3))(next@16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6): dependencies: ai: 7.0.158(zod@4.4.3) nitro: 3.0.260903-beta undici: 8.12.3 optionalDependencies: - '@vercel/connect': 2.6.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.0) + '@vercel/connect': 2.7.0(ai@7.0.158(zod@4.4.3))(eve@1.0.0-rc.1) next: 16.3.3(@types/node@24.19.2)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react: 19.2.6 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 81d5713..cfca979 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,2 +1,3 @@ minimumReleaseAgeExclude: - - eve@1.0.0-rc.0 + - eve@1.0.0-rc.1 + - "@vercel/connect@2.7.0"