fix(server-elysia): Add Node.js compatibility and VoltOps Console support#993
Conversation
🦋 Changeset detectedLatest commit: 81f024e The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
📝 WalkthroughWalkthroughAdded optional resumable-stream configuration and dependency; migrated server startup from Bun-specific listen to a Node.js Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant NodeHTTP as Node HTTP Server
participant Elysia as Elysia App
participant ResStream as Resumable Stream Adapter
Client->>NodeHTTP: TCP HTTP request
NodeHTTP->>NodeHTTP: Construct Web Request from Node req
NodeHTTP->>Elysia: app.fetch(request)
Elysia->>ResStream: Check resumableStream adapter/config
ResStream-->>Elysia: Provide stream handling behavior
Elysia-->>NodeHTTP: Response (headers, status, body stream)
NodeHTTP->>NodeHTTP: Map headers/status, pipe body to res
NodeHTTP->>Client: Stream response and finish
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@packages/server-elysia/src/app-factory.ts`:
- Around line 66-67: Remove the unnecessary `as any` on the `a2a` entry: pass
`resolvedDeps` directly to registerA2ARoutes because it already matches
ServerProviderDeps; for the `mcp` entry replace the unsafe `as any` with a
precise cast that exposes only the mcp piece (e.g. cast to McpDeps or use
Pick<typeof resolvedDeps, 'mcp'>) so registerMcpRoutes receives the expected
McpDeps while preserving type safety for resolvedDeps, referencing
registerA2ARoutes, registerMcpRoutes, resolvedDeps, McpDeps and
ServerProviderDeps.
🧹 Nitpick comments (2)
packages/server-elysia/src/elysia-server-provider.ts (2)
80-84: Replaceconsole.errorwith the class logger.The
ElysiaServerProviderclass has access tothis.loggerfrom the base class. Usingconsole.errorbypasses the structured logging infrastructure.Proposed fix
} catch (error) { - console.error("Request error:", error); + this.logger.error("Request error:", { error }); res.statusCode = 500; res.end("Internal Server Error"); }
65-78: Consider iterative streaming with backpressure handling.The recursive
pump()function has two concerns:
- Stack depth: For responses with many chunks, deep recursion could risk stack overflow (though V8 typically handles tail-call-like patterns well).
- Backpressure:
res.write()returnsfalsewhen the internal buffer is full, signaling the caller should wait for the'drain'event before writing more data. Ignoring this can cause memory pressure under load.Iterative approach with backpressure
if (response.body) { const reader = response.body.getReader(); - const pump = async (): Promise<void> => { - const { done, value } = await reader.read(); - if (done) { - res.end(); - return; - } - res.write(value); - await pump(); - }; - await pump(); + while (true) { + const { done, value } = await reader.read(); + if (done) { + res.end(); + break; + } + const canContinue = res.write(value); + if (!canContinue) { + await new Promise<void>((resolve) => res.once("drain", resolve)); + } + } } else { res.end(); }
omeraplak
left a comment
There was a problem hiding this comment.
Hey @Artist-MOBAI ,
Thank you so much 🥳
Hey Omer, thanks a ton! Great to meet you. I’m part of @AdventureX-RGE (China’s largest hackathon). I’ll be in the US in a few months and would love to grab a coffee and chat if you’re around! |
Hey, that’s awesome! I’m almost always in San Francisco. When you’re here, feel free to message me here or on Discord. I’d be happy to grab a coffee together. ☕️ |
Problem
When using
@voltagent/server-elysiaand connecting to VoltOps Console, the dashboard keeps spinning indefinitely and never loads, while@voltagent/server-honoworks correctly with the exact same project setup.Reproduction Steps
@voltagent/server-elysianpm run dev(using Node.js runtime, not Bun)http://localhost:3141) and attempt to connect@voltagent/server-hono)Observed Symptoms
After investigation, the following issues were observed:
Infinite Loading Spinner
"Local Connection Blocked by Browser" Error
CORS Errors in Browser Console
/agents,/workflows,/tools,/observability/health, etc.API Requests Not Responding (when tested with curl)
$ curl http://localhost:3141/agents # No response, exits with code 28 (connection timeout)Environment
@voltagent/server-elysia@voltagent/server-honoworks correctly in the same environmentComparison with server-hono
To verify this is an
server-elysiaspecific issue, I created two identical projects:@voltagent/server-hono@voltagent/server-elysiaBoth projects have identical agent configurations, tools, and workflows. The only difference is the server package used.
Root Cause Analysis
After comparing
@voltagent/server-elysiawith@voltagent/server-hono, three key issues were identified:1. Missing
@voltagent/resumable-streamsIntegrationserver-honointegratesresolveResumableStreamDepsto enable VoltOps Console connectivity:server-elysiawas missing this integration entirely, causing Console to fail to establish connection with the local server.2. Elysia's
app.listen()Doesn't Work in Node.jsElysia is designed primarily for Bun runtime. The
app.listen()method relies on Bun's native server implementation and does not function correctly in Node.js environment:server-honouses@hono/node-server'sserve()function which properly bridges Hono's fetch API to Node.js HTTP server. Since there's no equivalent@elysia/node-serverpackage, manual bridging is required.3. Incompatible CORS Default Values
Elysia's
@elysiajs/corshas different default values compared to Hono'scorsmiddleware:credentialsfalsetruecredentials: truewithorigin: "*"allowedHeadersx-voltagent-devare rejectedChanges
1.
package.jsonAdded
@voltagent/resumable-streamsdependency:2.
src/app-factory.tsAdded resumable-streams integration:
Fixed CORS configuration with sensible defaults:
3.
src/elysia-server-provider.tsReplaced
app.listen()with Node.js HTTP server:Summary
@voltagent/resumable-streamsintegrationresolveResumableStreamDepscallapp.listen()doesn't work in Node.jscredentials: false)Summary by cubic
Fixes VoltOps Console connectivity and Node.js compatibility in @voltagent/server-elysia. Console now loads correctly and API endpoints respond when running under Node.js.
Bug Fixes
Dependencies
Written for commit 81f024e. Summary will update on new commits.
Summary by CodeRabbit
New Features
Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.