mirror of
https://github.com/vercel/eve.git
synced 2026-09-20 05:35:39 +08:00
dfe0d181a0
Signed-off-by: Timo Lins <me@timo.sh>
125 lines
5.0 KiB
Plaintext
125 lines
5.0 KiB
Plaintext
---
|
|
title: "SvelteKit"
|
|
description: "Run an eve agent and a SvelteKit app as one project with the eveSvelteKit Vite plugin."
|
|
---
|
|
|
|
`eve/sveltekit` runs a SvelteKit frontend and an eve agent as one project instead of two services. The `eveSvelteKit()` Vite plugin puts both on one dev server and one Vercel deploy, and [`useEveAgent`](./use-eve-agent-svelte) finds the mounted routes on its own. There's no CORS to configure and no URL env vars to keep in sync.
|
|
|
|
## Prerequisites
|
|
|
|
- The `eve` package installed in your project (`npm install eve@latest`).
|
|
- An existing eve agent directory. If you don't have one, start from [Getting started](../../getting-started).
|
|
- A SvelteKit app to mount the agent in.
|
|
|
|
## Register the Vite plugin
|
|
|
|
Add `eveSvelteKit()` before `sveltekit()`:
|
|
|
|
```ts title="vite.config.ts"
|
|
import { sveltekit } from "@sveltejs/kit/vite";
|
|
import { eveSvelteKit } from "eve/sveltekit";
|
|
import { defineConfig } from "vite";
|
|
|
|
export default defineConfig({
|
|
plugins: [eveSvelteKit(), sveltekit()],
|
|
});
|
|
```
|
|
|
|
The plugin looks for an `agent/` folder in the SvelteKit project root. Pass `eveRoot` when the agent lives elsewhere:
|
|
|
|
```ts
|
|
export default defineConfig({
|
|
plugins: [
|
|
eveSvelteKit({
|
|
eveRoot: "../my-agent",
|
|
}),
|
|
sveltekit(),
|
|
],
|
|
});
|
|
```
|
|
|
|
The plugin accepts only two options, `eveRoot` and `eveBuildCommand`.
|
|
|
|
## Call the binding
|
|
|
|
With the plugin in `vite.config.ts`, components call [`useEveAgent`](./use-eve-agent-svelte) from `eve/svelte` and don't pass a host:
|
|
|
|
```svelte
|
|
<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>
|
|
```
|
|
|
|
The browser still needs a production authentication policy. See [Authenticate browser requests](./overview#authenticate-browser-requests) for the default fail-closed behavior and channel configuration.
|
|
|
|
## Dev vs deploy topology
|
|
|
|
- **Local dev.** `npm run dev` boots the eve dev server next to SvelteKit and proxies the eve routes to it, so the browser only ever hits the SvelteKit origin. `npm run build && npm run preview` behaves the same way: the preview server gets its own eve route proxy and either reuses the shared eve server or starts one.
|
|
- **Vercel.** The SvelteKit app and the eve runtime deploy as a single project. On Vercel builds the plugin adds Build Output [`services`](https://vercel.com/docs/services) for eve and a `routes` entry that sends `/eve/v1/**` to that service before filesystem routing; the SvelteKit app remains the default app. No `vercel.json` is required. By default the generated service runs the installed eve binary from the SvelteKit app's dependencies, so the agent directory does not need its own `package.json`. When the agent needs its own build step, set `eveBuildCommand`:
|
|
|
|
```ts
|
|
export default defineConfig({
|
|
plugins: [
|
|
eveSvelteKit({
|
|
eveBuildCommand: "npm run build:eve",
|
|
}),
|
|
sveltekit(),
|
|
],
|
|
});
|
|
```
|
|
|
|
- **Non-Vercel hosts.** When the eve service runs on a separate origin, pass `host` directly to `useEveAgent`:
|
|
|
|
```ts
|
|
const agent = useEveAgent({
|
|
host: "https://agent.example.com",
|
|
});
|
|
```
|
|
|
|
## Managing vercel.json yourself
|
|
|
|
When `vercel.json` declares [`services`](https://vercel.com/docs/services), the plugin generates nothing and your configuration owns routing. It must include the eve service (`framework: "eve"`) and a rewrite that exposes the eve transport, or the build fails:
|
|
|
|
```json title="vercel.json"
|
|
{
|
|
"services": {
|
|
"web": { "root": ".", "framework": "sveltekit" },
|
|
"eve": { "root": "agent", "framework": "eve", "buildCommand": "eve build" }
|
|
},
|
|
"rewrites": [{ "source": "/eve/v1/(.*)", "destination": { "service": "eve" } }]
|
|
}
|
|
```
|
|
|
|
### Migrating from experimentalServices
|
|
|
|
Earlier versions of the plugin wrote the legacy `experimentalServices` field into `vercel.json`. Vercel no longer routes that model, so the plugin now ignores the field and warns when it sees one. Migrate either way:
|
|
|
|
- **Generated (default).** Delete `vercel.json` (or just its `experimentalServices` block) and set the project's Framework Preset back to SvelteKit. The plugin generates the eve service and its routing on every Vercel build.
|
|
- **Hand-maintained.** Replace `experimentalServices` with the stable `services` and `rewrites` shown above, and keep the Services Framework Preset.
|
|
|
|
## What to read next
|
|
|
|
- [`useEveAgent` (Svelte)](./use-eve-agent-svelte): the binding API
|
|
- [Auth & route protection](../auth-and-route-protection)
|
|
- [Deployment](../deployment/overview)
|