Skip to content

Commit 70a5387

Browse files
committed
add openrouter functionality
1 parent ffa9f11 commit 70a5387

7 files changed

+73
-10
lines changed

CONTRIBUTING.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,11 @@ git clone https://github.com/stackblitz/bolt.new.git
5656
pnpm install
5757
```
5858

59-
3. Create a `.env.local` file in the root directory and add your Anthropic API key:
59+
3. Create a `.env.local` file in the root directory and add your Anthropic or OpenRouter API key:
6060

6161
```
6262
ANTHROPIC_API_KEY=XXX
63+
OPENROUTER_API_KEY=XXX
6364
```
6465

6566
Optionally, you can set the debug level:

app/lib/.server/llm/api-key.ts

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { env } from 'node:process';
22

3-
export function getAPIKey(cloudflareEnv: Env) {
4-
/**
5-
* The `cloudflareEnv` is only used when deployed or when previewing locally.
6-
* In development the environment variables are available through `env`.
7-
*/
8-
return env.ANTHROPIC_API_KEY || cloudflareEnv.ANTHROPIC_API_KEY;
3+
export function getAPIKeys(cloudflareEnv: Env) {
4+
return {
5+
openRouter: env.OPENROUTER_API_KEY || cloudflareEnv.OPENROUTER_API_KEY,
6+
anthropic: env.ANTHROPIC_API_KEY || cloudflareEnv.ANTHROPIC_API_KEY,
7+
};
98
}

app/lib/.server/llm/model.ts

+19
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,15 @@
11
import { createAnthropic } from '@ai-sdk/anthropic';
2+
import { createOpenRouter } from "@openrouter/ai-sdk-provider";
3+
4+
5+
export function getModel(apiKeys: { openRouter?: string; anthropic?: string }) {
6+
if (apiKeys.openRouter) {
7+
return getOpenRouterModel(apiKeys.openRouter);
8+
} else if (apiKeys.anthropic) {
9+
return getAnthropicModel(apiKeys.anthropic);
10+
}
11+
throw new Error('No valid API key found for OpenRouter or Anthropic');
12+
}
213

314
export function getAnthropicModel(apiKey: string) {
415
const anthropic = createAnthropic({
@@ -7,3 +18,11 @@ export function getAnthropicModel(apiKey: string) {
718

819
return anthropic('claude-3-5-sonnet-20240620');
920
}
21+
22+
export function getOpenRouterModel(apiKey: string) {
23+
const openRouter = createOpenRouter({
24+
apiKey,
25+
});
26+
27+
return openRouter('anthropic/claude-3.5-sonnet:beta');
28+
}

app/lib/.server/llm/stream-text.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { streamText as _streamText, convertToCoreMessages } from 'ai';
2-
import { getAPIKey } from '~/lib/.server/llm/api-key';
3-
import { getAnthropicModel } from '~/lib/.server/llm/model';
2+
import { getAPIKeys } from '~/lib/.server/llm/api-key';
3+
import { getModel } from '~/lib/.server/llm/model';
44
import { MAX_TOKENS } from './constants';
55
import { getSystemPrompt } from './prompts';
66

@@ -22,8 +22,9 @@ export type Messages = Message[];
2222
export type StreamingOptions = Omit<Parameters<typeof _streamText>[0], 'model'>;
2323

2424
export function streamText(messages: Messages, env: Env, options?: StreamingOptions) {
25+
const apiKeys = getAPIKeys(env);
2526
return _streamText({
26-
model: getAnthropicModel(getAPIKey(env)),
27+
model: getModel(apiKeys),
2728
system: getSystemPrompt(),
2829
maxTokens: MAX_TOKENS,
2930
headers: {

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@iconify-json/svg-spinners": "^1.1.2",
4444
"@lezer/highlight": "^1.2.0",
4545
"@nanostores/react": "^0.7.2",
46+
"@openrouter/ai-sdk-provider": "^0.0.5",
4647
"@radix-ui/react-dialog": "^1.1.1",
4748
"@radix-ui/react-dropdown-menu": "^2.1.1",
4849
"@remix-run/cloudflare": "^2.10.2",

pnpm-lock.yaml

+41
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

worker-configuration.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
interface Env {
22
ANTHROPIC_API_KEY: string;
3+
OPENROUTER_API_KEY: string;
34
}

0 commit comments

Comments
 (0)