Skip to content

Commit b322cf4

Browse files
authored
Feature/Elysia server integration (#898)
* feat(server-elysia): add elysia server integration * fix(server-elysia): address technical violations and improve error handling - Fix documentation links and repository references in README and notices - Implement body caching in auth middleware to support multiple JSON reads - Improve error status code mapping for A2A and Tool routes - Fix mutation bugs in OpenAPI document generation - Correct pagination logic and query parsing in agent routes - Fix SSE bridge abort handling and MCP argument parsing - Update tests to match constructor signature and improve mocks * fix(server-elysia): update zod version and fix syncpack formatting * fix(server-elysia): add server-elysia documentation to the website - Updated overview.md - Update authentication.md - Updated server-architecture.md * docs(server-elysia): fix incorrect types in server-architecture.md
1 parent b841593 commit b322cf4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+8933
-53
lines changed

.changeset/full-crews-battle.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
"@voltagent/server-elysia": major
3+
"@voltagent/server-core": minor
4+
---
5+
6+
feat: Initial release of @voltagent/server-elysia
7+
8+
# @voltagent/server-elysia
9+
10+
## 1.0.0
11+
12+
### Major Changes
13+
14+
- Initial release of Elysia server implementation for VoltAgent
15+
- Full feature parity with server-hono including:
16+
- Agent execution endpoints (text, stream, chat, object)
17+
- Workflow execution and lifecycle management
18+
- Tool execution and discovery
19+
- MCP (Model Context Protocol) support
20+
- A2A (Agent-to-Agent) communication
21+
- Observability and tracing
22+
- Logging endpoints
23+
- Authentication with authNext support
24+
- Custom endpoint configuration
25+
- CORS configuration
26+
- WebSocket support
27+
28+
### Features
29+
30+
- **High Performance**: Built on Elysia, optimized for speed and low latency
31+
- **Type Safety**: Full TypeScript support with strict typing
32+
- **Flexible Configuration**: Support for both `configureApp` and `configureFullApp` patterns
33+
- **Auth Support**: JWT authentication with public route configuration via `authNext`
34+
- **Extensible**: Easy to add custom routes, middleware, and plugins
35+
- **OpenAPI/Swagger**: Built-in API documentation via @elysiajs/swagger
36+
- **MCP Support**: Full Model Context Protocol implementation with SSE streaming
37+
- **WebSocket Support**: Real-time updates and streaming capabilities
38+
39+
### Dependencies
40+
41+
- `@voltagent/core`: ^1.5.1
42+
- `@voltagent/server-core`: ^1.0.36
43+
- `@voltagent/mcp-server`: ^1.0.3
44+
- `@voltagent/a2a-server`: ^1.0.2
45+
- `elysia`: ^1.1.29
46+
47+
### Peer Dependencies
48+
49+
- `@voltagent/core`: ^1.x
50+
- `elysia`: ^1.x

packages/server-core/src/server/base-provider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export abstract class BaseServerProvider implements IServerProvider {
184184
});
185185
}
186186

187-
private collectFeatureEndpoints(): ServerEndpointSummary[] {
187+
protected collectFeatureEndpoints(): ServerEndpointSummary[] {
188188
const endpoints: ServerEndpointSummary[] = [];
189189
const seen = new Set<string>();
190190

packages/server-elysia/README.md

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# @voltagent/server-elysia
2+
3+
Elysia server implementation for VoltAgent - A high-performance, type-safe server provider built on [Elysia](https://elysiajs.com/).
4+
5+
## Features
6+
7+
- 🚀 **High Performance**: Built on Elysia, one of the fastest TypeScript frameworks
8+
- 🔒 **Type Safe**: Full TypeScript support with strict typing
9+
- 🔐 **Authentication**: JWT authentication with flexible configuration via `authNext`
10+
- 🌐 **CORS Support**: Easy CORS configuration for cross-origin requests
11+
- 📡 **WebSocket Support**: Real-time streaming and updates
12+
- 🛠️ **Extensible**: Easy to add custom routes, middleware, and plugins
13+
- 📚 **OpenAPI/Swagger**: Built-in API documentation via @elysiajs/swagger
14+
- 🔌 **MCP Support**: Full Model Context Protocol implementation
15+
16+
## Installation
17+
18+
```bash
19+
pnpm add @voltagent/server-elysia elysia
20+
```
21+
22+
## Quick Start
23+
24+
```typescript
25+
import { createVoltAgent } from "@voltagent/core";
26+
import { elysiaServer } from "@voltagent/server-elysia";
27+
import { openai } from "@ai-sdk/openai";
28+
29+
const volt = createVoltAgent({
30+
agents: [
31+
{
32+
id: "my-agent",
33+
model: openai("gpt-4"),
34+
instructions: "You are a helpful assistant",
35+
},
36+
],
37+
server: elysiaServer({
38+
port: 3141,
39+
}),
40+
});
41+
42+
volt.start();
43+
```
44+
45+
## Configuration
46+
47+
### Basic Configuration
48+
49+
```typescript
50+
elysiaServer({
51+
port: 3141,
52+
hostname: "0.0.0.0",
53+
enableSwaggerUI: true,
54+
});
55+
```
56+
57+
### CORS Configuration
58+
59+
```typescript
60+
elysiaServer({
61+
cors: {
62+
origin: "https://example.com",
63+
allowMethods: ["GET", "POST", "PUT", "DELETE"],
64+
allowHeaders: ["Content-Type", "Authorization"],
65+
credentials: true,
66+
},
67+
});
68+
```
69+
70+
### Authentication with authNext
71+
72+
```typescript
73+
import { jwtAuth } from "@voltagent/server-elysia";
74+
75+
elysiaServer({
76+
authNext: {
77+
provider: jwtAuth({ secret: process.env.JWT_SECRET! }),
78+
publicRoutes: ["GET /health", "POST /webhooks/*"],
79+
},
80+
});
81+
```
82+
83+
### Custom Routes
84+
85+
```typescript
86+
elysiaServer({
87+
configureApp: (app) => {
88+
// Add custom routes
89+
app.get("/health", () => ({ status: "ok" }));
90+
91+
// Add route groups
92+
app.group("/api/v2", (app) => app.get("/users", () => ({ users: [] })));
93+
94+
// Add middleware
95+
app.use(customPlugin);
96+
},
97+
});
98+
```
99+
100+
### Full App Configuration
101+
102+
For complete control over route and middleware ordering:
103+
104+
```typescript
105+
elysiaServer({
106+
configureFullApp: ({ app, routes, middlewares }) => {
107+
// Apply middleware first
108+
middlewares.cors();
109+
middlewares.auth();
110+
111+
// Register routes in custom order
112+
routes.agents();
113+
114+
// Add custom routes between VoltAgent routes
115+
app.get("/custom", () => ({ custom: true }));
116+
117+
// Register remaining routes
118+
routes.workflows();
119+
routes.tools();
120+
routes.doc();
121+
},
122+
});
123+
```
124+
125+
## API Endpoints
126+
127+
Once running, the following endpoints are available:
128+
129+
### Agent Endpoints
130+
131+
- `GET /agents` - List all agents
132+
- `GET /agents/:id` - Get agent details
133+
- `POST /agents/:id/text` - Generate text
134+
- `POST /agents/:id/stream` - Stream text generation
135+
- `POST /agents/:id/chat` - Stream chat messages
136+
- `POST /agents/:id/object` - Generate structured objects
137+
138+
### Workflow Endpoints
139+
140+
- `GET /workflows` - List all workflows
141+
- `GET /workflows/:id` - Get workflow details
142+
- `POST /workflows/:id/execute` - Execute a workflow
143+
- `POST /workflows/:id/stream` - Stream workflow execution
144+
145+
### Tool Endpoints
146+
147+
- `GET /tools` - List all tools
148+
- `POST /tools/:name/execute` - Execute a tool
149+
150+
### Observability Endpoints
151+
152+
- `GET /observability` - Get observability data
153+
- `GET /observability/traces` - List traces
154+
- `GET /observability/traces/:traceId` - Get specific trace
155+
156+
### Documentation
157+
158+
- `GET /` - Landing page
159+
- `GET /doc` - OpenAPI specification
160+
- `GET /ui` - Swagger UI (if enabled)
161+
162+
## Comparison with server-hono
163+
164+
Both `server-hono` and `server-elysia` provide the same VoltAgent features, but with different framework implementations:
165+
166+
| Feature | server-hono | server-elysia |
167+
| ----------- | --------------------- | --------------------------------------- |
168+
| Performance | Fast | Faster (Elysia is optimized for speed) |
169+
| Validation | Zod (Native) | TypeBox (via Zod Adapter) |
170+
| OpenAPI | Via @hono/zod-openapi | Via @elysiajs/swagger (built-in) |
171+
| Middleware | Hono middleware | Elysia plugins |
172+
| Type Safety | Full TypeScript | Full TypeScript with enhanced inference |
173+
| Bundle Size | ~28KB | ~26KB |
174+
175+
### Architecture & Validation
176+
177+
One key difference is how validation is handled:
178+
179+
- **server-hono** uses `zod` natively for validation and OpenAPI generation.
180+
- **server-elysia** uses `TypeBox` (Elysia's native validation engine) for maximum performance.
181+
182+
Since VoltAgent's core schemas are defined in `zod` (in `@voltagent/server-core`), `server-elysia` includes a specialized **Zod Adapter**. This adapter automatically transforms Zod schemas into TypeBox/JSON Schema format at runtime, ensuring:
183+
184+
1. **Compatibility**: All existing VoltAgent schemas work out of the box.
185+
2. **Performance**: Validation runs using Elysia's optimized TypeBox compiler.
186+
3. **Documentation**: OpenAPI specs are generated correctly using Elysia's Swagger plugin.
187+
188+
Choose `server-elysia` if you:
189+
190+
- Want maximum performance
191+
- Prefer Elysia's plugin ecosystem
192+
- Need built-in Eden (type-safe client)
193+
194+
Choose `server-hono` if you:
195+
196+
- Are already familiar with Hono
197+
- Need compatibility with Cloudflare Workers
198+
- Want a more mature ecosystem
199+
200+
## Advanced Usage
201+
202+
### Custom Middleware
203+
204+
```typescript
205+
import { Elysia } from "elysia";
206+
207+
const customMiddleware = new Elysia().derive(({ request }) => ({
208+
userId: request.headers.get("x-user-id"),
209+
}));
210+
211+
elysiaServer({
212+
configureApp: (app) => {
213+
app.use(customMiddleware);
214+
},
215+
});
216+
```
217+
218+
### Error Handling
219+
220+
```typescript
221+
elysiaServer({
222+
configureApp: (app) => {
223+
app.onError(({ code, error }) => {
224+
if (code === "NOT_FOUND") {
225+
return { error: "Route not found" };
226+
}
227+
return { error: error.message };
228+
});
229+
},
230+
});
231+
```
232+
233+
## License
234+
235+
MIT
236+
237+
## Links
238+
239+
- [VoltAgent Documentation](https://voltagent.dev)
240+
- [Elysia Documentation](https://elysiajs.com)
241+
- [GitHub Repository](https://github.com/VoltAgent/voltagent)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Third Party Notices
2+
3+
This package includes or depends upon third-party code. The following is a list of such dependencies and their licenses:
4+
5+
## Elysia
6+
7+
- **License**: MIT
8+
- **Repository**: https://github.com/elysiajs/elysia
9+
- **Copyright**: Copyright (c) 2023 Saltyaom
10+
11+
## @elysiajs/cors
12+
13+
- **License**: MIT
14+
- **Repository**: https://github.com/elysiajs/elysia-cors
15+
- **Copyright**: Copyright (c) 2023 Saltyaom
16+
17+
## @elysiajs/swagger
18+
19+
- **License**: MIT
20+
- **Repository**: https://github.com/elysiajs/elysia-swagger
21+
22+
## @sinclair/typebox
23+
24+
- **License**: MIT
25+
- **Repository**: https://github.com/sinclairzx81/typebox
26+
27+
## zod
28+
29+
- **License**: MIT
30+
- **Repository**: https://github.com/colinhacks/zod
31+
32+
## zod-to-json-schema
33+
34+
- **License**: MIT
35+
- **Repository**: https://github.com/StefanTerdell/zod-to-json-schema
36+
- **Copyright**: Copyright (c) 2023 Stefan Terdell
37+
38+
## VoltAgent Core Packages
39+
40+
- **License**: MIT
41+
- **Repository**: https://github.com/VoltAgent/voltagent
42+
- **Copyright**: Copyright (c) VoltAgent Contributors
43+
44+
---
45+
46+
For complete license texts, please refer to the respective package repositories.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { Agent, VoltAgent } from "@voltagent/core";
2+
import { elysiaServer } from "@voltagent/server-elysia";
3+
4+
// Mock model to avoid API keys requirement for the example
5+
const mockModel = {
6+
provider: "mock",
7+
modelId: "mock-model",
8+
specificationVersion: "v1",
9+
defaultObjectGenerationMode: "json",
10+
doGenerate: async () => ({
11+
text: "Hello from mock model!",
12+
finishReason: "stop",
13+
usage: { promptTokens: 10, completionTokens: 5 },
14+
rawCall: { rawPrompt: null, rawSettings: {} },
15+
}),
16+
doStream: async () => ({
17+
stream: new ReadableStream({
18+
start(controller) {
19+
controller.enqueue({ type: "text-delta", textDelta: "Hello " });
20+
controller.enqueue({ type: "text-delta", textDelta: "from " });
21+
controller.enqueue({ type: "text-delta", textDelta: "mock " });
22+
controller.enqueue({ type: "text-delta", textDelta: "model!" });
23+
controller.enqueue({
24+
type: "finish",
25+
finishReason: "stop",
26+
usage: { promptTokens: 10, completionTokens: 5 },
27+
});
28+
controller.close();
29+
},
30+
}),
31+
rawCall: { rawPrompt: null, rawSettings: {} },
32+
}),
33+
} as any;
34+
35+
// Define a simple agent
36+
const agent = new Agent({
37+
name: "example-agent",
38+
instructions: "You are a helpful assistant.",
39+
model: mockModel,
40+
});
41+
42+
// Initialize VoltAgent with Elysia server
43+
const _client = new VoltAgent({
44+
agents: {
45+
agent,
46+
},
47+
server: elysiaServer({
48+
port: 3000,
49+
}),
50+
});

0 commit comments

Comments
 (0)