- 人工智能
- AI Agent
- Agent 框架
- 后端
- 工具调用
【免费下载链接】eve
The Open Framework for Building Agents
本文以apps/frameworks/sveltekit/下的 SvelteKit 示例应用为主体,讲解如何通过eveSvelteKit()Vite 插件将 eve agent 与 SvelteKit 应用整合为单一项目:从agent/目录的指令、工具与频道配置,到useEveAgentSvelte 绑定驱动的控制台 UI,再到本地开发与 Vercel 部署的完整拓扑。读完本文,你将掌握在 SvelteKit 中挂载 eve 运行时的全部接线方式、插件的两个配置项(eveRoot/eveBuildCommand)的语义,以及从源码层面理解 dev 代理与 Vercel Build Output 生成机制的原理。
1. 一体化项目的整体结构
这个示例的定位很直接:一个嵌入了 eve agent 的 SvelteKit 应用,通过eve/sveltekit提供的 Vite 插件完成集成(见 README):
import { eveSvelteKit } from "eve/sveltekit"; export default defineConfig({ plugins: [eveSvelteKit(), sveltekit()], });仓库中的实际配置(vite.config.ts)在插件链中还加入了 Tailwind 与 Vercel 适配器:
import adapter from "@sveltejs/adapter-vercel"; import { sveltekit } from "@sveltejs/kit/vite"; import tailwindcss from "@tailwindcss/vite"; import { eveSvelteKit } from "eve/sveltekit"; import { defineConfig } from "vite"; export default defineConfig({ plugins: [eveSvelteKit(), tailwindcss(), sveltekit({ adapter: adapter() })], });注意插件注册顺序:eveSvelteKit()写在sveltekit()之前,且插件内部以enforce: "post"挂入,确保在 SvelteKit 自身配置解析后再注入代理与构建产物逻辑(见 插件入口)。
整个 demo 的目录分工:
agent/:eve agent 本体——指令、工具、频道配置;src/lib/:基于 eve 的 Svelte 绑定构建的小型 agent 控制台,具备流式输出、推理块与工具调用渲染;src/routes/:SvelteKit 路由,首页即控制台。
依赖方面(package.json):@sveltejs/kit、svelte5、vite8、@sveltejs/adapter-vercel与eve(workspace 依赖)。
2. agent/ 目录:指令、模型、工具与频道
2.1 模型与推理配置
agent/agent.ts 用defineAgent声明 agent,开启了 Anthropic 的自适应思考模式:
import { defineAgent } from "eve"; export default defineAgent({ model: "anthropic/claude-opus-4.7", modelOptions: { providerOptions: { anthropic: { thinking: { type: "adaptive", display: "summarized" }, effort: "high", }, }, }, });thinking.display: "summarized"意味着思考内容会以摘要形式回传给前端,这正好对应控制台中ReasoningBlock组件对reasoning类型消息片的渲染(流式时标记state === "streaming")。
2.2 内置天气工具
agent/tools/get_weather.ts 演示了用 zod 定义入参 schema 的工具:
import { defineTool } from "eve/tools"; import { never } from "eve/tools/approval"; import { z } from "zod"; export default defineTool({ approval: never(), description: "Get the current weather for a city.", inputSchema: z.object({ city: z.string(), }), async execute(input) { const city = input.city; await sleep(300); return { city, temperatureF: 72, condition: "Sunny", summary: `Sunny in ${city} with a light breeze.`, }; }, });两个要点:approval: never()表示该工具永不触发人工审批;300ms 的sleep是为了让前端能观察到工具调用从input-available(Running)到output-available(Completed)的状态流转。
2.3 频道与鉴权
agent/channels/eve.ts 配置了eve频道:
import { localDev, none } from "eve/channels/auth"; import { eveChannel } from "eve/channels/eve"; // 示例接受匿名流量以便部署后的 demo 可直接点击体验; // 公开暴露 agent 前请换成真实 provider(Auth.js、Clerk、vercelOidc() 等)。 export default eveChannel({ auth: [localDev(), none()], });源码注释明确说明:none()只适合受部署保护门禁约束的演示环境;浏览器端生产环境仍需一套生产鉴权策略,可参考 前端总览 中默认的 fail-closed 行为与频道配置说明。指令文件 agent/instructions.md 则将 agent 限定为"内嵌在 SvelteKit 应用中的天气助手"。
3. 注册 Vite 插件:eveRoot 与 eveBuildCommand
完整指南见 SvelteKit 前端文档。前置条件:项目已安装eve包、存在一个 eve agent 目录、有一个要挂载 agent 的 SvelteKit 应用。
插件默认在 SvelteKit 项目根目录查找agent/文件夹;当 agent 位于别处时,用eveRoot指定(相对路径基于 SvelteKit 项目根,也支持绝对路径——见 resolveApplicationRoot):
export default defineConfig({ plugins: [ eveSvelteKit({ eveRoot: "../my-agent", }), sveltekit(), ], });插件只接受两个选项(EveSvelteKitPluginOptions):
| 选项 | 类型 | 作用 |
|---|---|---|
eveRoot | string? | eve 应用根目录,相对 SvelteKit 项目根(除非是绝对路径),默认即 SvelteKit 项目根 |
eveBuildCommand | string? | 在生成的 Vercel eve service 内部构建 eve 应用的命令;默认直接运行 SvelteKit 依赖中的 eve 二进制(node <path>/eve/bin/eve.js build) |
因此 agent 目录本身不需要独立的package.json,eve 运行时复用 SvelteKit 应用依赖里安装的eve。只有当 agent 需要自己的构建步骤时才设置eveBuildCommand:
export default defineConfig({ plugins: [ eveSvelteKit({ eveBuildCommand: "npm run build:eve", }), sveltekit(), ], });4. 在组件中调用 useEveAgent
插件注册后,组件直接从eve/svelte调用useEveAgent(),不需要传 host——它会自动发现挂载在本应用源站上的路由(浏览器只访问 SvelteKit origin,没有 CORS、也没有需要同步的 URL 环境变量):
<script lang="ts"> import { useEveAgent } from "eve/svelte"; const agent = useEveAgent(); let message = $state(""); let isBusy = $derived(agent.status === "submitted" || agent.status === "streaming"); let isInputDisabled = $derived(isBusy || agent.status === "resuming"); async function handleSubmit() { const text = message.trim(); if (!text || isInputDisabled) return; message = ""; await agent.send(text); } </script> <form onsubmit={(event) => { event.preventDefault(); void handleSubmit(); }}> <input bind:value={message} disabled={isInputDisabled} /> <button type="submit" disabled={isInputDisabled}>Send</button> </form>绑定返回的对象不是 Svelte store:状态字段(data、status、error、events、session)是 Svelte 5 风格的响应式 getter,可直接在模板、$derived、$effect中读取;命令(send、respond、prewarm、resume、cancel、reset)是普通方法。完整接口见 useEveAgent (Svelte) 与 Svelte 绑定实现。
示例控制台的关键实现
EveAgentConsole.svelte 展示了这套绑定的典型用法:
- 用
agent.status推导isBusy(submitted/streaming)与isResuming(resuming),据此禁用输入; - 消息按
message.parts分类型渲染:text直出、reasoning交给 ReasoningBlock、file渲染附件卡片、dynamic-tool交给 ToolBlock; - 流式生成期间发送按钮变为"停止"按钮,调用
agent.cancel()请求取消服务端持久化的这一轮; - HITL 审批/提问通过
agent.respond(responses)回传,ToolBlock 会渲染approval-requested等状态并提供选项按钮; - StatusDot 把
ready/submitted/streaming/error状态映射为不同颜色圆点。
5. dev 与部署拓扑(源码级解析)
5.1 本地开发:代理到共享 eve dev server
插件在serve阶段把/eve/v1前缀(EVE_ROUTE_PREFIX,定义于 protocol/routes.ts)代理到 eve 服务器。代理目标按以下顺序解析(resolveEveDevProxyTarget):
- 环境变量
EVE_BASE_URL已设置时,直接使用其指向的 origin; - 否则查找该应用已经存在且健康的共享 eve dev server(基于
.eve/sveltekit-dev-server.json注册表,带 30s 超时与锁文件,见 dev-server.ts); - 仍无则新启动
eve dev --no-ui --port 0。
所以npm run dev启动的是"SvelteKit + 旁边的 eve dev server",浏览器始终只命中 SvelteKit origin;npm run build && npm run preview同理——preview 服务器同样拿到一份 eve 路由代理(对应插件中env.isPreview分支写入preview.proxy的逻辑,见 index.ts)。
在仓库内运行这个 demo:
pnpm --filter framework-sveltekit dev其他常用脚本(package.json):build/build:sveltekit(vite build)、preview(vite preview)、typecheck(svelte-kit sync && tsc --noEmit)。
5.2 Vercel:单项目部署,无需 vercel.json
在 Vercel 构建时,插件把 SvelteKit 应用与 eve 运行时作为同一项目部署。构建期间插件向 Vercel Build Output 追加 eve 的services条目,并插入一条把/eve/v1/**先于文件系统路由转给该 service 的routes规则;SvelteKit 应用仍是默认 app。合并动作发生在 SSR 构建的closeBundle阶段,写入.vercel/output/config.json(mergeGeneratedVercelServicesConfig、closeBundle handler)。服务路由的匹配与 path transform 逻辑实现在 shared/vercel-services.ts。
因此不需要vercel.json。当 agent 需要自己的构建步骤时,用eveBuildCommand覆盖默认的node <path>/eve/bin/eve.js build。
5.3 非 Vercel 托管
当 eve service 跑在独立 origin 上时,直接把host传给绑定:
const agent = useEveAgent({ host: "https://agent.example.com", });5.4 自行维护 vercel.json
如果vercel.json已声明services,插件不再生成任何配置,路由完全由你的文件拥有(插件源码中对应mode: "root"的跳过分支,见 EnsureEveVercelServicesConfigResult)。此时文件必须包含 eve service(framework: "eve")以及暴露 eve transport 的 rewrite,否则构建失败:
{ "services": { "web": { "root": ".", "framework": "sveltekit" }, "eve": { "root": "agent", "framework": "eve", "buildCommand": "eve build" } }, "rewrites": [{ "source": "/eve/v1/(.*)", "destination": { "service": "eve" } }] }从旧版experimentalServices迁移有两个方向:
- 生成式(默认):删除
vercel.json(或仅删掉其experimentalServices块),并把项目 Framework Preset 设回 SvelteKit,插件会在每次 Vercel 构建时生成 eve service 与路由; - 手工维护式:把
experimentalServices替换为上文稳定的services+rewrites,并保留 Services Framework Preset。
6. 小结
| 关注点 | 本示例的做法 | 依据 |
|---|---|---|
| 插件注册 | plugins: [eveSvelteKit(), tailwindcss(), sveltekit({ adapter })] | vite.config.ts |
| agent 位置 | 项目根agent/(默认,无需eveRoot) | agent 目录 |
| 前端绑定 | useEveAgent(),不传 host | EveAgentConsole.svelte |
| 本地运行 | pnpm --filter framework-sveltekit dev | package.json |
| Vercel 部署 | 插件生成 service 与/eve/v1/**路由,无需 vercel.json | vercel-services.ts |
| 独立 origin | useEveAgent({ host }) | SvelteKit 指南 |
这套接线让 SvelteKit 前端与 eve agent 在开发时共享一个源站(靠 Vite 代理)、在部署时共享一个项目(靠 Build Output services),前端拿到的是一套与 React/Vue 等绑定共享语义的响应式 API——流式消息、推理摘要、工具状态与 HITL 审批都能以 Svelte 5 runes 的方式直接投影到 UI。
- 人工智能
- AI Agent
- Agent 框架
- 后端
- 工具调用
【免费下载链接】eve
The Open Framework for Building Agents
相关推荐
eve 与 Nuxt 4 一体化集成:用 eve/nuxt 模块把 Agent 嵌入 Nuxt 应用
eve 与 Nuxt 4 一体化集成:用 eve/nuxt 模块把 Agent 嵌入 Nuxt 应用 eve 是一个开放式的 Agent 框架(The Open
人工智能AI AgentAgent 框架后端工具调用SvelteKit Vite 插件(@sveltejs/kit/vite)完全指南:sveltekit() 入口与 Config 全量配置解析
SvelteKit Vite 插件(@sveltejs/kit/vite)完全指南:sveltekit 入口与 Config 全量配置解析 SvelteKit
Web框架后端前端vite-plugin-qiankun 微前端插件配置指南:从零到一的完整实践
vite plugin qiankun 微前端插件配置指南:从零到一的完整实践 在当今前端开发领域,微前端架构正逐渐成为大型应用的首选方案。vite plugi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考