diff --git a/README.md b/README.md index 3be15fd..75be4e9 100644 --- a/README.md +++ b/README.md @@ -228,6 +228,8 @@ the models BigSet uses for schema inference and agents. OpenRouter is pay-as-you-go; $5-10 is plenty to start. +**Using a different gateway:** BigSet also works with [OrcaRouter](https://www.orcarouter.ai), an OpenAI-compatible router that exposes 200+ models (OpenAI, Anthropic, Google, DeepSeek, ...) behind a single API key. Set `OPENROUTER_BASE_URL=https://api.orcarouter.ai/v1` in `.env` and paste your `sk-orca-...` key into the setup screen. OrcaRouter uses the same `provider/model` id format as OpenRouter, so BigSet's default model slugs (e.g. `anthropic/claude-sonnet-4.6`) work as-is. + > **Note:** root `.env` is the only local env file. If you edit Convex functions in `frontend/convex/`, run `make convex-push` to deploy the changes. > **Free tier:** cloud signed-in accounts get **2,500 row operations per calendar month** (resets on the 1st, UTC). Local mode bypasses the cloud quota and uses your TinyFish/OpenRouter accounts directly. @@ -296,6 +298,7 @@ If you want a completely fresh start: `make clean` then `make dev`. | Variable | Required | Where to get it | |----------|----------|----------------| | `CONVEX_SELF_HOSTED_ADMIN_KEY` | Auto | Auto-generated by `make dev` on first run | +| `OPENROUTER_BASE_URL` | Optional | Defaults to `https://openrouter.ai/api/v1`. Point BigSet at any OpenAI-compatible gateway, e.g. OrcaRouter (`https://api.orcarouter.ai/v1`). | | `LOCAL_KEYCHAIN_PORT`, `LOCAL_KEYCHAIN_TOKEN`, `BIGSET_LOCAL_WORKSPACE_ID` | Auto | Auto-generated by `make dev` for local OS keychain access | | `RESEND_API_KEY` | Optional | For "dataset ready" emails. Leave blank to skip. | | `NEXT_PUBLIC_POSTHOG_KEY` | Optional | For product analytics. Leave blank to disable. | diff --git a/backend/src/local-credentials.ts b/backend/src/local-credentials.ts index a6a5b4b..fb2ff69 100644 --- a/backend/src/local-credentials.ts +++ b/backend/src/local-credentials.ts @@ -254,11 +254,21 @@ export async function verifyOpenRouterApiKey(apiKey: string): Promise { await withFetchTimeout( async (signal) => { - const response = await fetch(`${baseUrl}/key`, { + let response = await fetch(`${baseUrl}/key`, { headers: { Authorization: `Bearer ${apiKey}` }, signal, }); + // OpenAI-compatible gateways that don't implement OpenRouter's `/key` + // endpoint (e.g. OrcaRouter) can still be verified with a lightweight + // authenticated request — `/models` returns 401 for invalid keys. + if (response.status === 404) { + response = await fetch(`${baseUrl}/models`, { + headers: { Authorization: `Bearer ${apiKey}` }, + signal, + }); + } + if (!response.ok) { if (response.status === 401 || response.status === 403) { throw new Error("OpenRouter rejected that API key.");