diff --git a/.env.example b/.env.example index ae64fdc..ae52385 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ # API Keys for AI providers OPENAI_API_KEY=sk-... -ANTHROPIC_API_KEY=sk-ant-... +OPENROUTER_API_KEY=sk-or-... GOOGLE_GENAI_API_KEY=... # Sentry Configuration (optional) diff --git a/.github/workflows/daily-tests.yml b/.github/workflows/daily-tests.yml index 2a59339..68ab08e 100644 --- a/.github/workflows/daily-tests.yml +++ b/.github/workflows/daily-tests.yml @@ -106,7 +106,7 @@ jobs: continue-on-error: true env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} GOOGLE_GENAI_API_KEY: ${{ secrets.GOOGLE_GENAI_API_KEY }} CO_API_KEY: ${{ secrets.CO_API_KEY }} run: npm run test -- -j=12 diff --git a/.github/workflows/pr-tests.yml b/.github/workflows/pr-tests.yml index 1701da3..8d15fa3 100644 --- a/.github/workflows/pr-tests.yml +++ b/.github/workflows/pr-tests.yml @@ -100,7 +100,7 @@ jobs: continue-on-error: true env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} GOOGLE_GENAI_API_KEY: ${{ secrets.GOOGLE_GENAI_API_KEY }} CO_API_KEY: ${{ secrets.CO_API_KEY }} run: npm run test -- -j=12 @@ -201,7 +201,7 @@ jobs: continue-on-error: true env: OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }} + OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} GOOGLE_GENAI_API_KEY: ${{ secrets.GOOGLE_GENAI_API_KEY }} CO_API_KEY: ${{ secrets.CO_API_KEY }} run: npm run test -- -j=12 diff --git a/README.md b/README.md index 590f8a7..78ad583 100644 --- a/README.md +++ b/README.md @@ -752,7 +752,7 @@ Create a `.env` file with your API keys: ```bash OPENAI_API_KEY=sk-... -ANTHROPIC_API_KEY=sk-ant-... +OPENROUTER_API_KEY=sk-or-... GOOGLE_GENAI_API_KEY=... ``` @@ -814,7 +814,7 @@ jobs: with: platform: python # or 'node', or leave empty for both openai-api-key: ${{ secrets.OPENAI_API_KEY }} - anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} + openrouter-api-key: ${{ secrets.OPENROUTER_API_KEY }} google-genai-api-key: ${{ secrets.GOOGLE_GENAI_API_KEY }} ``` @@ -829,7 +829,7 @@ jobs: | `sentry-python-path` | No | `""` | Path to local sentry-python for editable install | | `sentry-javascript-path` | No | `""` | Path to local sentry-javascript for linking | | `openai-api-key` | Yes | - | OpenAI API key | -| `anthropic-api-key` | Yes | - | Anthropic API key | +| `openrouter-api-key` | Yes | - | OpenRouter API key for Anthropic-compatible requests | | `google-genai-api-key` | Yes | - | Google GenAI API key | ### Action Outputs @@ -854,7 +854,7 @@ jobs: parallel: 8 sentry-python-path: ${{ github.workspace }} openai-api-key: ${{ secrets.OPENAI_API_KEY }} - anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} + openrouter-api-key: ${{ secrets.OPENROUTER_API_KEY }} google-genai-api-key: ${{ secrets.GOOGLE_GENAI_API_KEY }} - name: Check results diff --git a/action.yml b/action.yml index 8816901..1014160 100644 --- a/action.yml +++ b/action.yml @@ -42,8 +42,8 @@ inputs: openai-api-key: description: "OpenAI API key" required: true - anthropic-api-key: - description: "Anthropic API key" + openrouter-api-key: + description: "OpenRouter API key used through the Anthropic-compatible endpoint" required: true google-genai-api-key: description: "Google GenAI API key" @@ -100,7 +100,7 @@ runs: working-directory: ${{ github.action_path }} env: OPENAI_API_KEY: ${{ inputs.openai-api-key }} - ANTHROPIC_API_KEY: ${{ inputs.anthropic-api-key }} + OPENROUTER_API_KEY: ${{ inputs.openrouter-api-key }} GOOGLE_GENAI_API_KEY: ${{ inputs.google-genai-api-key }} run: | set +e diff --git a/src/runner/browser-runner.ts b/src/runner/browser-runner.ts index 7af9efc..9e160f9 100644 --- a/src/runner/browser-runner.ts +++ b/src/runner/browser-runner.ts @@ -320,7 +320,7 @@ export default defineConfig({ window.SENTRY_DSN = ${JSON.stringify(sentryDsn)}; window.RUN_ID = ${JSON.stringify(runId)}; window.OPENAI_API_KEY = ${JSON.stringify(process.env.OPENAI_API_KEY || "")}; - window.ANTHROPIC_API_KEY = ${JSON.stringify(process.env.ANTHROPIC_API_KEY || "")}; + window.OPENROUTER_API_KEY = ${JSON.stringify(process.env.OPENROUTER_API_KEY || "")}; window.GOOGLE_GENAI_API_KEY = ${JSON.stringify(process.env.GOOGLE_GENAI_API_KEY || "")}; window.testComplete = false; `); @@ -430,7 +430,7 @@ declare global { SENTRY_DSN: string; RUN_ID: string; OPENAI_API_KEY: string; - ANTHROPIC_API_KEY: string; + OPENROUTER_API_KEY: string; GOOGLE_GENAI_API_KEY: string; testComplete: boolean; } diff --git a/src/runner/cloudflare-runner.ts b/src/runner/cloudflare-runner.ts index 7c5b59f..c2e3e69 100644 --- a/src/runner/cloudflare-runner.ts +++ b/src/runner/cloudflare-runner.ts @@ -197,7 +197,7 @@ export class CloudflareRunner { // Always regenerate .dev.vars with current API keys (setup may be cached) const devVars = [ `OPENAI_API_KEY=${process.env.OPENAI_API_KEY || ""}`, - `ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY || ""}`, + `OPENROUTER_API_KEY=${process.env.OPENROUTER_API_KEY || ""}`, `GOOGLE_GENAI_API_KEY=${process.env.GOOGLE_GENAI_API_KEY || ""}`, ].join("\n"); await fs.writeFile(path.join(workDir, ".dev.vars"), devVars); diff --git a/src/runner/javascript-runner.ts b/src/runner/javascript-runner.ts index 1fb61a6..44ca505 100644 --- a/src/runner/javascript-runner.ts +++ b/src/runner/javascript-runner.ts @@ -194,7 +194,7 @@ export class JavaScriptRunner { SENTRY_DSN: sentryDsn, RUN_ID: runId, OPENAI_API_KEY: process.env.OPENAI_API_KEY || "", - ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "", + OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || "", GOOGLE_GENAI_API_KEY: process.env.GOOGLE_GENAI_API_KEY || "", }; diff --git a/src/runner/php-runner.ts b/src/runner/php-runner.ts index aefb38a..1b9fed9 100644 --- a/src/runner/php-runner.ts +++ b/src/runner/php-runner.ts @@ -285,7 +285,7 @@ return [ SENTRY_TRACES_SAMPLE_RATE: "1.0", RUN_ID: runId, OPENAI_API_KEY: process.env.OPENAI_API_KEY || "", - ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || "", + OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || "", GOOGLE_GENAI_API_KEY: process.env.GOOGLE_GENAI_API_KEY || "", }; diff --git a/src/runner/python-runner.ts b/src/runner/python-runner.ts index 601e0f7..44da5d4 100644 --- a/src/runner/python-runner.ts +++ b/src/runner/python-runner.ts @@ -174,7 +174,7 @@ ${dependencies.map(d => ` ${d},`).join('\n')} SENTRY_DSN: sentryDsn, RUN_ID: runId, OPENAI_API_KEY: process.env.OPENAI_API_KEY || '', - ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY || '', + OPENROUTER_API_KEY: process.env.OPENROUTER_API_KEY || '', GOOGLE_GENAI_API_KEY: process.env.GOOGLE_GENAI_API_KEY || '', }; diff --git a/src/runner/templates/agents/cloudflare/langgraph/template.njk b/src/runner/templates/agents/cloudflare/langgraph/template.njk index 12e8f2c..a64ac9c 100644 --- a/src/runner/templates/agents/cloudflare/langgraph/template.njk +++ b/src/runner/templates/agents/cloudflare/langgraph/template.njk @@ -66,7 +66,8 @@ import { z } from "zod"; {% if provider == "anthropic" %} const llm = new ChatAnthropic({ modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, - anthropicApiKey: env.ANTHROPIC_API_KEY, + anthropicApiKey: env.OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", }); {% else %} const llm = new ChatOpenAI({ diff --git a/src/runner/templates/agents/cloudflare/vercel/template.njk b/src/runner/templates/agents/cloudflare/vercel/template.njk index 2a24911..2aa4acc 100644 --- a/src/runner/templates/agents/cloudflare/vercel/template.njk +++ b/src/runner/templates/agents/cloudflare/vercel/template.njk @@ -43,7 +43,10 @@ import { createOpenAI } from "@ai-sdk/openai"; {% block dynamic_imports %} {% if provider == "anthropic" %} - const anthropic = createAnthropic({ apiKey: env.ANTHROPIC_API_KEY }); + const anthropic = createAnthropic({ + apiKey: env.OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", + }); {% else %} const openai = createOpenAI({ apiKey: env.OPENAI_API_KEY }); {% endif %} diff --git a/src/runner/templates/agents/nextjs/vercel/template.njk b/src/runner/templates/agents/nextjs/vercel/template.njk index 1d40094..22eb32d 100644 --- a/src/runner/templates/agents/nextjs/vercel/template.njk +++ b/src/runner/templates/agents/nextjs/vercel/template.njk @@ -24,7 +24,11 @@ const { ToolLoopAgent, tool, jsonSchema, stepCountIs } = await import("ai"); const { generateText, streamText, tool, jsonSchema, stepCountIs } = await import("ai"); {% endif %} {% if provider == "anthropic" %} -const { anthropic } = await import("@ai-sdk/anthropic"); +const { createAnthropic } = await import("@ai-sdk/anthropic"); +const anthropic = createAnthropic({ + apiKey: process.env.OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", +}); {% else %} const { openai } = await import("@ai-sdk/openai"); {% endif %} diff --git a/src/runner/templates/agents/node/langgraph/template.njk b/src/runner/templates/agents/node/langgraph/template.njk index 63d1fa1..64fae03 100644 --- a/src/runner/templates/agents/node/langgraph/template.njk +++ b/src/runner/templates/agents/node/langgraph/template.njk @@ -61,6 +61,8 @@ const tools = [ {% if provider == "anthropic" %} const llm = new ChatAnthropic({ + anthropicApiKey: process.env.OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, }); {% else %} diff --git a/src/runner/templates/agents/node/vercel/template.njk b/src/runner/templates/agents/node/vercel/template.njk index 327bb92..cc96f48 100644 --- a/src/runner/templates/agents/node/vercel/template.njk +++ b/src/runner/templates/agents/node/vercel/template.njk @@ -31,7 +31,11 @@ const { streamText, tool, jsonSchema, stepCountIs } = await import("ai"); const { generateText, tool, jsonSchema, stepCountIs } = await import("ai"); {% endif %} {% if provider == "anthropic" %} -const { anthropic } = await import("@ai-sdk/anthropic"); +const { createAnthropic } = await import("@ai-sdk/anthropic"); +const anthropic = createAnthropic({ + apiKey: process.env.OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", +}); {% else %} const { openai } = await import("@ai-sdk/openai"); {% endif %} diff --git a/src/runner/templates/agents/python/langgraph/template.njk b/src/runner/templates/agents/python/langgraph/template.njk index 2237d8a..cdb07b8 100644 --- a/src/runner/templates/agents/python/langgraph/template.njk +++ b/src/runner/templates/agents/python/langgraph/template.njk @@ -33,7 +33,8 @@ from langchain_core.messages import HumanMessage, SystemMessage # Initialize ChatAnthropic for LangGraph llm = ChatAnthropic( model="{{ inputs[0].model }}", - api_key=os.environ.get("ANTHROPIC_API_KEY"), + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", ) {% else %} # Initialize ChatOpenAI for LangGraph diff --git a/src/runner/templates/llm/browser/anthropic/template.njk b/src/runner/templates/llm/browser/anthropic/template.njk index cccc8c0..f0b9330 100644 --- a/src/runner/templates/llm/browser/anthropic/template.njk +++ b/src/runner/templates/llm/browser/anthropic/template.njk @@ -20,15 +20,16 @@ {% block dynamic_imports %} const { default: Anthropic } = await import('@anthropic-ai/sdk'); - const ANTHROPIC_API_KEY = window.ANTHROPIC_API_KEY; - if (!ANTHROPIC_API_KEY) { - log('ERROR: ANTHROPIC_API_KEY not found in window'); - throw new Error('ANTHROPIC_API_KEY not provided'); + const OPENROUTER_API_KEY = window.OPENROUTER_API_KEY; + if (!OPENROUTER_API_KEY) { + log('ERROR: OPENROUTER_API_KEY not found in window'); + throw new Error('OPENROUTER_API_KEY not provided'); } // WARNING: API key is exposed in browser - this is for testing only! const anthropic = new Anthropic({ - apiKey: ANTHROPIC_API_KEY, + apiKey: OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", dangerouslyAllowBrowser: true }); diff --git a/src/runner/templates/llm/browser/langchain/template.njk b/src/runner/templates/llm/browser/langchain/template.njk index 5cc2fda..a02cd32 100644 --- a/src/runner/templates/llm/browser/langchain/template.njk +++ b/src/runner/templates/llm/browser/langchain/template.njk @@ -26,10 +26,10 @@ const { HumanMessage, SystemMessage, AIMessage } = await import("@langchain/core/messages"); {% if provider == "anthropic" %} - const ANTHROPIC_API_KEY = window.ANTHROPIC_API_KEY; - if (!ANTHROPIC_API_KEY) { - log('ERROR: ANTHROPIC_API_KEY not found in window'); - throw new Error('ANTHROPIC_API_KEY not provided'); + const OPENROUTER_API_KEY = window.OPENROUTER_API_KEY; + if (!OPENROUTER_API_KEY) { + log('ERROR: OPENROUTER_API_KEY not found in window'); + throw new Error('OPENROUTER_API_KEY not provided'); } {% else %} const OPENAI_API_KEY = window.OPENAI_API_KEY; @@ -45,7 +45,8 @@ {% if provider == "anthropic" %} const chat = new ChatAnthropic({ modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, - anthropicApiKey: ANTHROPIC_API_KEY, + anthropicApiKey: OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", }); log('LangChain ChatAnthropic initialized with createLangChainCallbackHandler'); diff --git a/src/runner/templates/llm/cloudflare/anthropic/template.njk b/src/runner/templates/llm/cloudflare/anthropic/template.njk index fe839af..685b26e 100644 --- a/src/runner/templates/llm/cloudflare/anthropic/template.njk +++ b/src/runner/templates/llm/cloudflare/anthropic/template.njk @@ -22,7 +22,10 @@ import Anthropic from "@anthropic-ai/sdk"; {% endblock %} {% block dynamic_imports %} - const rawClient = new Anthropic({ apiKey: env.ANTHROPIC_API_KEY }); + const rawClient = new Anthropic({ + apiKey: env.OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", + }); const client = Sentry.instrumentAnthropicAiClient(rawClient); {% endblock %} diff --git a/src/runner/templates/llm/cloudflare/langchain/template.njk b/src/runner/templates/llm/cloudflare/langchain/template.njk index 7baba45..736f22d 100644 --- a/src/runner/templates/llm/cloudflare/langchain/template.njk +++ b/src/runner/templates/llm/cloudflare/langchain/template.njk @@ -30,7 +30,8 @@ import { HumanMessage, SystemMessage, AIMessage } from "@langchain/core/messages {% if provider == "anthropic" %} const chat = new ChatAnthropic({ modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, - anthropicApiKey: env.ANTHROPIC_API_KEY, + anthropicApiKey: env.OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", }); {% else %} const chat = new ChatOpenAI({ diff --git a/src/runner/templates/llm/nextjs/anthropic/template.njk b/src/runner/templates/llm/nextjs/anthropic/template.njk index 7dd4f7a..d279802 100644 --- a/src/runner/templates/llm/nextjs/anthropic/template.njk +++ b/src/runner/templates/llm/nextjs/anthropic/template.njk @@ -20,13 +20,16 @@ {% block dynamic_imports %} const { default: Anthropic } = await import('@anthropic-ai/sdk'); -const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; -if (!ANTHROPIC_API_KEY) { - console.error('ERROR: ANTHROPIC_API_KEY not found in environment'); - throw new Error('ANTHROPIC_API_KEY not provided'); +const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY; +if (!OPENROUTER_API_KEY) { + console.error('ERROR: OPENROUTER_API_KEY not found in environment'); + throw new Error('OPENROUTER_API_KEY not provided'); } -const anthropic = new Anthropic({ apiKey: ANTHROPIC_API_KEY }); +const anthropic = new Anthropic({ + apiKey: OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", +}); const client = Sentry.instrumentAnthropicAiClient(anthropic); console.log('Anthropic client initialized and instrumented'); {% endblock %} diff --git a/src/runner/templates/llm/nextjs/langchain/template.njk b/src/runner/templates/llm/nextjs/langchain/template.njk index 6b6cda6..501669b 100644 --- a/src/runner/templates/llm/nextjs/langchain/template.njk +++ b/src/runner/templates/llm/nextjs/langchain/template.njk @@ -26,10 +26,10 @@ const { ChatOpenAI } = await import("@langchain/openai"); const { HumanMessage, SystemMessage, AIMessage } = await import("@langchain/core/messages"); {% if provider == "anthropic" %} -const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY; -if (!ANTHROPIC_API_KEY) { - console.error('ERROR: ANTHROPIC_API_KEY not found in environment'); - throw new Error('ANTHROPIC_API_KEY not provided'); +const OPENROUTER_API_KEY = process.env.OPENROUTER_API_KEY; +if (!OPENROUTER_API_KEY) { + console.error('ERROR: OPENROUTER_API_KEY not found in environment'); + throw new Error('OPENROUTER_API_KEY not provided'); } {% else %} const OPENAI_API_KEY = process.env.OPENAI_API_KEY; @@ -43,7 +43,8 @@ const callbackHandler = Sentry.createLangChainCallbackHandler(); {% if provider == "anthropic" %} const chat = new ChatAnthropic({ modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, - anthropicApiKey: ANTHROPIC_API_KEY, + anthropicApiKey: OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", }); console.log('LangChain ChatAnthropic initialized with createLangChainCallbackHandler'); {% else %} diff --git a/src/runner/templates/llm/node/anthropic/template.njk b/src/runner/templates/llm/node/anthropic/template.njk index 0ace001..62d3530 100644 --- a/src/runner/templates/llm/node/anthropic/template.njk +++ b/src/runner/templates/llm/node/anthropic/template.njk @@ -19,7 +19,10 @@ {% block dynamic_imports %} const { default: Anthropic } = await import("@anthropic-ai/sdk"); -const client = new Anthropic(); +const client = new Anthropic({ + apiKey: process.env.OPENROUTER_API_KEY, + baseURL: "https://openrouter.ai/api", +}); {% endblock %} {% block test %} diff --git a/src/runner/templates/llm/node/langchain/template.njk b/src/runner/templates/llm/node/langchain/template.njk index feac175..b4323ac 100644 --- a/src/runner/templates/llm/node/langchain/template.njk +++ b/src/runner/templates/llm/node/langchain/template.njk @@ -26,6 +26,8 @@ const { ChatOpenAI } = await import("@langchain/openai"); const { HumanMessage, SystemMessage, AIMessage } = await import("@langchain/core/messages"); {% if provider == "anthropic" %} const chat = new ChatAnthropic({ + anthropicApiKey: process.env.OPENROUTER_API_KEY, + anthropicApiUrl: "https://openrouter.ai/api", modelName: {% if causeAPIError %}"invalid-model"{% else %}"{{ inputs[0].model }}"{% endif %}, }); {% else %} diff --git a/src/runner/templates/llm/python/anthropic/template.njk b/src/runner/templates/llm/python/anthropic/template.njk index 59181b0..34cc49b 100644 --- a/src/runner/templates/llm/python/anthropic/template.njk +++ b/src/runner/templates/llm/python/anthropic/template.njk @@ -32,16 +32,22 @@ import httpx {% block inject_api_error %} {% if causeAPIError %} -respx.route(host="api.anthropic.com").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) +respx.route(host="openrouter.ai").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) respx.mock.start() {% endif %} {% endblock %} {% block setup %} {% if isAsync %} -client = AsyncAnthropic() +client = AsyncAnthropic( + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", +) {% else %} -client = Anthropic() +client = Anthropic( + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", +) {% endif %} {% endblock %} diff --git a/src/runner/templates/llm/python/langchain/template.njk b/src/runner/templates/llm/python/langchain/template.njk index d7749bc..1236f84 100644 --- a/src/runner/templates/llm/python/langchain/template.njk +++ b/src/runner/templates/llm/python/langchain/template.njk @@ -34,7 +34,7 @@ import httpx {% block inject_api_error %} {% if causeAPIError %} {% if provider == "anthropic" %} -respx.route(host="api.anthropic.com").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) +respx.route(host="openrouter.ai").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) {% else %} respx.route(host="api.openai.com").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) {% endif %} @@ -45,7 +45,11 @@ respx.mock.start() {% block setup %} {% set input = inputs[0] %} {% if provider == "anthropic" %} -chat = ChatAnthropic(model="{{ input.model }}") +chat = ChatAnthropic( + model="{{ input.model }}", + api_key=os.environ["OPENROUTER_API_KEY"], + base_url="https://openrouter.ai/api", +) {% else %} chat = ChatOpenAI(model="{{ input.model }}") {% endif %} diff --git a/src/runner/templates/llm/python/litellm/template.njk b/src/runner/templates/llm/python/litellm/template.njk index 16ec884..55fcccc 100644 --- a/src/runner/templates/llm/python/litellm/template.njk +++ b/src/runner/templates/llm/python/litellm/template.njk @@ -73,7 +73,7 @@ import httpx {% block inject_api_error %} {% if causeAPIError %} {% if provider == "anthropic" %} -respx.route(host="api.anthropic.com").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) +respx.route(host="openrouter.ai").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) {% else %} respx.route(host="api.openai.com").mock(return_value=httpx.Response(500, json={"error": {"message": "Server error", "type": "server_error"}})) {% endif %} @@ -105,7 +105,7 @@ sentry_sdk.init( {% else %} stream = litellm.responses( {% endif %} - model="{% if provider == "anthropic" %}anthropic{% else %}openai{% endif %}/{{ input.model }}", + model="{% if provider == "anthropic" %}openrouter/anthropic{% else %}openai{% endif %}/{{ input.model }}", {% set instructions = extractInstructions(input.messages) | trim %} {% if instructions %} instructions="{{ instructions }}", @@ -131,7 +131,7 @@ sentry_sdk.init( {% else %} response = litellm.responses( {% endif %} - model="{% if provider == "anthropic" %}anthropic{% else %}openai{% endif %}/{{ input.model }}", + model="{% if provider == "anthropic" %}openrouter/anthropic{% else %}openai{% endif %}/{{ input.model }}", {% set instructions = extractInstructions(input.messages) | trim %} {% if instructions %} instructions="{{ instructions }}", @@ -147,7 +147,7 @@ sentry_sdk.init( {% else %} stream = litellm.completion( {% endif %} - model="{% if provider == "anthropic" %}anthropic{% else %}openai{% endif %}/{{ input.model }}", + model="{% if provider == "anthropic" %}openrouter/anthropic{% else %}openai{% endif %}/{{ input.model }}", messages={{ convertMessages(input.messages) }}, stream=True, ) @@ -169,7 +169,7 @@ sentry_sdk.init( {% else %} response = litellm.completion( {% endif %} - model="{% if provider == "anthropic" %}anthropic{% else %}openai{% endif %}/{{ input.model }}", + model="{% if provider == "anthropic" %}openrouter/anthropic{% else %}openai{% endif %}/{{ input.model }}", messages={{ convertMessages(input.messages) }}, ) print(f"Turn {{ loop.index }} Response: {response.choices[0].message.content}")