SDKEdge runtime
Edge runtime
Cloudflare Workers, Vercel Edge, Deno Deploy — no OpenAI-SDK import, no `node:*` modules.
@cleverrouter/sdk/edge is a lighter entry that avoids the OpenAI SDK
import. No node:* modules, no Buffer, no eval — everything
works in runtimes that only expose Web APIs.
At a glance
| Install | bun add @cleverrouter/sdk@alpha |
| Import path | @cleverrouter/sdk/edge |
| Runtimes | Cloudflare Workers, Vercel Edge, Deno Deploy |
| Available endpoints | chat, stream, embed, rerank, transcribe, listModels |
Vercel Edge Function
import { createCleverRouter } from '@cleverrouter/sdk/edge';
export const runtime = 'edge';
export async function POST(req: Request) {
const cr = createCleverRouter({
apiKey: process.env.CLEVERROUTER_API_KEY!,
});
const { messages } = await req.json();
const completion = await cr.chat({
model: 'mistral/mistral-small-3.2',
messages,
});
return Response.json(completion);
}Streaming on the edge
Wrap the SDK's AsyncIterable into a ReadableStream and forward
as SSE:
import { createCleverRouter } from '@cleverrouter/sdk/edge';
export const runtime = 'edge';
export async function POST(req: Request) {
const cr = createCleverRouter({ apiKey: process.env.CLEVERROUTER_API_KEY! });
const { messages } = await req.json();
const stream = cr.stream({
model: 'mistral/mistral-small-3.2',
messages,
});
const encoder = new TextEncoder();
const body = new ReadableStream({
async start(controller) {
try {
for await (const chunk of stream) {
const text = chunk.choices[0]?.delta?.content ?? '';
if (text) {
controller.enqueue(
encoder.encode(`data: ${JSON.stringify({ delta: text })}\n\n`),
);
}
}
controller.enqueue(encoder.encode('data: [DONE]\n\n'));
} catch (err) {
controller.error(err);
} finally {
controller.close();
}
},
});
return new Response(body, {
headers: {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache, no-transform',
'X-Accel-Buffering': 'no',
},
});
}Cloudflare Workers
import { createCleverRouter } from '@cleverrouter/sdk/edge';
export default {
async fetch(req: Request, env: { CLEVERROUTER_API_KEY: string }) {
const cr = createCleverRouter({ apiKey: env.CLEVERROUTER_API_KEY });
const { messages } = await req.json();
return Response.json(
await cr.chat({ model: 'mistral/mistral-small-3.2', messages }),
);
},
};The package's exports map advertises ./edge with the worker
condition, so wrangler picks the right artifact automatically.
Deno Deploy
import { createCleverRouter } from 'npm:@cleverrouter/sdk@alpha/edge';
const cr = createCleverRouter({ apiKey: Deno.env.get('CLEVERROUTER_API_KEY')! });
Deno.serve(async (req) => {
const { messages } = await req.json();
return Response.json(
await cr.chat({ model: 'mistral/mistral-small-3.2', messages }),
);
});What's missing vs the main entry
| Feature | @cleverrouter/sdk | @cleverrouter/sdk/edge |
|---|---|---|
cr.openai() shim | yes | no |
chat, stream | yes | yes |
embed, rerank | yes | yes |
transcribe | yes | yes |
listModels | yes | yes |
| React hooks | via /react | n/a |
| Bundle size impact | + openai peer dep | minimal |
Mix and match per file
Same SDK package — import @cleverrouter/sdk in Node.js / Bun
routes and @cleverrouter/sdk/edge from edge routes. Types and
error classes are shared.
Common gotchas
process.envdoesn't exist in Cloudflare Workers. Use theenvargument thatfetchreceives.Bufferdoesn't exist on the edge. UseUint8ArrayandTextEncoder/TextDecoder— the SDK already does.- Edge fetch quotas. Vercel and Cloudflare cap streamed connections per worker. Long-lived chat streams should run on Node.js or Bun routes — the edge is great for one-shot completions and proxy patterns.
Related
- SDK overview
- Streaming — wire format details.
- React hooks — pair with
/api/chaton the edge.