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

Installbun add @cleverrouter/sdk@alpha
Import path@cleverrouter/sdk/edge
RuntimesCloudflare Workers, Vercel Edge, Deno Deploy
Available endpointschat, stream, embed, rerank, transcribe, listModels

Vercel Edge Function

app/api/chat/route.ts
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:

app/api/stream/route.ts
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

worker.ts
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

main.ts
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() shimyesno
chat, streamyesyes
embed, rerankyesyes
transcribeyesyes
listModelsyesyes
React hooksvia /reactn/a
Bundle size impact+ openai peer depminimal

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.env doesn't exist in Cloudflare Workers. Use the env argument that fetch receives.
  • Buffer doesn't exist on the edge. Use Uint8Array and TextEncoder/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.