Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .changeset/full-crews-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
"@voltagent/server-elysia": major
"@voltagent/server-core": minor
---

feat: Initial release of @voltagent/server-elysia

# @voltagent/server-elysia

## 1.0.0

### Major Changes

- Initial release of Elysia server implementation for VoltAgent
- Full feature parity with server-hono including:
- Agent execution endpoints (text, stream, chat, object)
- Workflow execution and lifecycle management
- Tool execution and discovery
- MCP (Model Context Protocol) support
- A2A (Agent-to-Agent) communication
- Observability and tracing
- Logging endpoints
- Authentication with authNext support
- Custom endpoint configuration
- CORS configuration
- WebSocket support

### Features

- **High Performance**: Built on Elysia, optimized for speed and low latency
- **Type Safety**: Full TypeScript support with strict typing
- **Flexible Configuration**: Support for both `configureApp` and `configureFullApp` patterns
- **Auth Support**: JWT authentication with public route configuration via `authNext`
- **Extensible**: Easy to add custom routes, middleware, and plugins
- **OpenAPI/Swagger**: Built-in API documentation via @elysiajs/swagger
- **MCP Support**: Full Model Context Protocol implementation with SSE streaming
- **WebSocket Support**: Real-time updates and streaming capabilities

### Dependencies

- `@voltagent/core`: ^1.5.1
- `@voltagent/server-core`: ^1.0.36
- `@voltagent/mcp-server`: ^1.0.3
- `@voltagent/a2a-server`: ^1.0.2
- `elysia`: ^1.1.29

### Peer Dependencies

- `@voltagent/core`: ^1.x
- `elysia`: ^1.x
2 changes: 1 addition & 1 deletion packages/server-core/src/server/base-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ export abstract class BaseServerProvider implements IServerProvider {
});
}

private collectFeatureEndpoints(): ServerEndpointSummary[] {
protected collectFeatureEndpoints(): ServerEndpointSummary[] {
const endpoints: ServerEndpointSummary[] = [];
const seen = new Set<string>();

Expand Down
241 changes: 241 additions & 0 deletions packages/server-elysia/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
# @voltagent/server-elysia

Elysia server implementation for VoltAgent - A high-performance, type-safe server provider built on [Elysia](https://elysiajs.com/).

## Features

- 🚀 **High Performance**: Built on Elysia, one of the fastest TypeScript frameworks
- 🔒 **Type Safe**: Full TypeScript support with strict typing
- 🔐 **Authentication**: JWT authentication with flexible configuration via `authNext`
- 🌐 **CORS Support**: Easy CORS configuration for cross-origin requests
- 📡 **WebSocket Support**: Real-time streaming and updates
- 🛠️ **Extensible**: Easy to add custom routes, middleware, and plugins
- 📚 **OpenAPI/Swagger**: Built-in API documentation via @elysiajs/swagger
- 🔌 **MCP Support**: Full Model Context Protocol implementation

## Installation

```bash
pnpm add @voltagent/server-elysia elysia
```

## Quick Start

```typescript
import { createVoltAgent } from "@voltagent/core";
import { elysiaServer } from "@voltagent/server-elysia";
import { openai } from "@ai-sdk/openai";

const volt = createVoltAgent({
agents: [
{
id: "my-agent",
model: openai("gpt-4"),
instructions: "You are a helpful assistant",
},
],
server: elysiaServer({
port: 3141,
}),
});

volt.start();
```

## Configuration

### Basic Configuration

```typescript
elysiaServer({
port: 3141,
hostname: "0.0.0.0",
enableSwaggerUI: true,
});
```

### CORS Configuration

```typescript
elysiaServer({
cors: {
origin: "https://example.com",
allowMethods: ["GET", "POST", "PUT", "DELETE"],
allowHeaders: ["Content-Type", "Authorization"],
credentials: true,
},
});
```

### Authentication with authNext

```typescript
import { jwtAuth } from "@voltagent/server-elysia";

elysiaServer({
authNext: {
provider: jwtAuth({ secret: process.env.JWT_SECRET! }),
publicRoutes: ["GET /health", "POST /webhooks/*"],
},
});
```

### Custom Routes

```typescript
elysiaServer({
configureApp: (app) => {
// Add custom routes
app.get("/health", () => ({ status: "ok" }));

// Add route groups
app.group("/api/v2", (app) => app.get("/users", () => ({ users: [] })));

// Add middleware
app.use(customPlugin);
},
});
```

### Full App Configuration

For complete control over route and middleware ordering:

```typescript
elysiaServer({
configureFullApp: ({ app, routes, middlewares }) => {
// Apply middleware first
middlewares.cors();
middlewares.auth();

// Register routes in custom order
routes.agents();

// Add custom routes between VoltAgent routes
app.get("/custom", () => ({ custom: true }));

// Register remaining routes
routes.workflows();
routes.tools();
routes.doc();
},
});
```

## API Endpoints

Once running, the following endpoints are available:

### Agent Endpoints

- `GET /agents` - List all agents
- `GET /agents/:id` - Get agent details
- `POST /agents/:id/text` - Generate text
- `POST /agents/:id/stream` - Stream text generation
- `POST /agents/:id/chat` - Stream chat messages
- `POST /agents/:id/object` - Generate structured objects

### Workflow Endpoints

- `GET /workflows` - List all workflows
- `GET /workflows/:id` - Get workflow details
- `POST /workflows/:id/execute` - Execute a workflow
- `POST /workflows/:id/stream` - Stream workflow execution

### Tool Endpoints

- `GET /tools` - List all tools
- `POST /tools/:name/execute` - Execute a tool

### Observability Endpoints

- `GET /observability` - Get observability data
- `GET /observability/traces` - List traces
- `GET /observability/traces/:traceId` - Get specific trace

### Documentation

- `GET /` - Landing page
- `GET /doc` - OpenAPI specification
- `GET /ui` - Swagger UI (if enabled)

## Comparison with server-hono

Both `server-hono` and `server-elysia` provide the same VoltAgent features, but with different framework implementations:

| Feature | server-hono | server-elysia |
| ----------- | --------------------- | --------------------------------------- |
| Performance | Fast | Faster (Elysia is optimized for speed) |
| Validation | Zod (Native) | TypeBox (via Zod Adapter) |
| OpenAPI | Via @hono/zod-openapi | Via @elysiajs/swagger (built-in) |
| Middleware | Hono middleware | Elysia plugins |
| Type Safety | Full TypeScript | Full TypeScript with enhanced inference |
| Bundle Size | ~28KB | ~26KB |

### Architecture & Validation

One key difference is how validation is handled:

- **server-hono** uses `zod` natively for validation and OpenAPI generation.
- **server-elysia** uses `TypeBox` (Elysia's native validation engine) for maximum performance.

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:

1. **Compatibility**: All existing VoltAgent schemas work out of the box.
2. **Performance**: Validation runs using Elysia's optimized TypeBox compiler.
3. **Documentation**: OpenAPI specs are generated correctly using Elysia's Swagger plugin.

Choose `server-elysia` if you:

- Want maximum performance
- Prefer Elysia's plugin ecosystem
- Need built-in Eden (type-safe client)

Choose `server-hono` if you:

- Are already familiar with Hono
- Need compatibility with Cloudflare Workers
- Want a more mature ecosystem

## Advanced Usage

### Custom Middleware

```typescript
import { Elysia } from "elysia";

const customMiddleware = new Elysia().derive(({ request }) => ({
userId: request.headers.get("x-user-id"),
}));

elysiaServer({
configureApp: (app) => {
app.use(customMiddleware);
},
});
```

### Error Handling

```typescript
elysiaServer({
configureApp: (app) => {
app.onError(({ code, error }) => {
if (code === "NOT_FOUND") {
return { error: "Route not found" };
}
return { error: error.message };
});
},
});
```

## License

MIT

## Links

- [VoltAgent Documentation](https://voltagent.dev)
- [Elysia Documentation](https://elysiajs.com)
- [GitHub Repository](https://github.com/VoltAgent/voltagent)
46 changes: 46 additions & 0 deletions packages/server-elysia/THIRD_PARTY_NOTICES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Third Party Notices

This package includes or depends upon third-party code. The following is a list of such dependencies and their licenses:

## Elysia

- **License**: MIT
- **Repository**: https://github.com/elysiajs/elysia
- **Copyright**: Copyright (c) 2023 Saltyaom

## @elysiajs/cors

- **License**: MIT
- **Repository**: https://github.com/elysiajs/elysia-cors
- **Copyright**: Copyright (c) 2023 Saltyaom

## @elysiajs/swagger

- **License**: MIT
- **Repository**: https://github.com/elysiajs/elysia-swagger

## @sinclair/typebox

- **License**: MIT
- **Repository**: https://github.com/sinclairzx81/typebox

## zod

- **License**: MIT
- **Repository**: https://github.com/colinhacks/zod

## zod-to-json-schema

- **License**: MIT
- **Repository**: https://github.com/StefanTerdell/zod-to-json-schema
- **Copyright**: Copyright (c) 2023 Stefan Terdell

## VoltAgent Core Packages

- **License**: MIT
- **Repository**: https://github.com/VoltAgent/voltagent
- **Copyright**: Copyright (c) VoltAgent Contributors

---

For complete license texts, please refer to the respective package repositories.
50 changes: 50 additions & 0 deletions packages/server-elysia/example/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Agent, VoltAgent } from "@voltagent/core";
import { elysiaServer } from "@voltagent/server-elysia";

// Mock model to avoid API keys requirement for the example
const mockModel = {
provider: "mock",
modelId: "mock-model",
specificationVersion: "v1",
defaultObjectGenerationMode: "json",
doGenerate: async () => ({
text: "Hello from mock model!",
finishReason: "stop",
usage: { promptTokens: 10, completionTokens: 5 },
rawCall: { rawPrompt: null, rawSettings: {} },
}),
doStream: async () => ({
stream: new ReadableStream({
start(controller) {
controller.enqueue({ type: "text-delta", textDelta: "Hello " });
controller.enqueue({ type: "text-delta", textDelta: "from " });
controller.enqueue({ type: "text-delta", textDelta: "mock " });
controller.enqueue({ type: "text-delta", textDelta: "model!" });
controller.enqueue({
type: "finish",
finishReason: "stop",
usage: { promptTokens: 10, completionTokens: 5 },
});
controller.close();
},
}),
rawCall: { rawPrompt: null, rawSettings: {} },
}),
} as any;

// Define a simple agent
const agent = new Agent({
name: "example-agent",
instructions: "You are a helpful assistant.",
model: mockModel,
});

// Initialize VoltAgent with Elysia server
const _client = new VoltAgent({
agents: {
agent,
},
server: elysiaServer({
port: 3000,
}),
});
Loading