diff --git a/docs/provider-quirks.md b/docs/provider-quirks.md index f3be4e22a..d55905ecf 100644 --- a/docs/provider-quirks.md +++ b/docs/provider-quirks.md @@ -1303,7 +1303,7 @@ OpenRouter is a unified multi-provider routing gateway serving hundreds of third - **Provider Order & Exclusion Preferences**: `applyOpenAIGatewayRouting` in `packages/ai/src/providers/openai-shared.ts` injects catalog `openRouterRouting` preferences (`OpenRouterRouting` interface with `only?: string[]` and `order?: string[]`) into the top-level `provider` request parameter when `compat.isOpenRouterHost` is true. - **Anthropic `cache_control` Breakpoints**: `isOpenRouterAnthropicModel` (`packages/ai/src/providers/openai-shared.ts`) identifies models matching `provider === "openrouter"` and ID starting with `anthropic/`. On the Chat Completions wire, `applyOpenAIChatCompletionsPromptCachePolicy` (`openai-completions.ts`) attaches `cache_control: { type: "ephemeral" }` to the last non-empty text part of the latest message. On the Responses wire, `applyOpenAIResponsesPromptCachePolicy` (`openai-responses.ts`) sets `params.cache_control = cacheRetention === "long" ? { type: "ephemeral", ttl: "1h" } : { type: "ephemeral" }`. - **Catalog Default Max-Tokens Omission**: `resolveOpenAIOutputTokenParam` in `packages/ai/src/providers/openai-shared.ts` omits default output token limits (`max_tokens`, `max_completion_tokens`, `max_output_tokens`) when `isOpenRouterHost` is true and `maxTokensExplicit` is false. This prevents OpenRouter from filtering out upstreams whose advertised output ceiling is below catalog maximums when executing `provider.order` / `only` fallbacks; explicitly specified caller `maxTokens` are retained. -- **Custom Request Headers**: `getOpenRouterHeaders` in `packages/ai/src/utils/openrouter-headers.ts` attaches `User-Agent: Oh-My-Pi/`, `HTTP-Referer: https://omp.sh/`, `X-OpenRouter-Title: Oh-My-Pi`, `X-OpenRouter-Categories: cli-agent`, `X-OpenRouter-Cache: true`, and `X-OpenRouter-Cache-TTL: 3600` to all requests for edge response caching. +- **Custom Request Headers**: `getOpenRouterHeaders` in `packages/ai/src/utils/openrouter-headers.ts` attaches `User-Agent: omp/`, `HTTP-Referer: https://omp.sh/`, `X-OpenRouter-Title: omp`, `X-OpenRouter-Categories: cli-agent`, `X-OpenRouter-Cache: true`, and `X-OpenRouter-Cache-TTL: 3600` to all requests for edge response caching. ### Auth & usage - **Auth Key Validation via `/api/v1/auth/key`**: `loginOpenRouter` in `packages/ai/src/registry/openrouter.ts` configures API key validation using `validateApiKeyAgainstModelsEndpoint` targeted at `https://openrouter.ai/api/v1/auth/key`. Public `/api/v1/models` returns HTTP 200 for unauthenticated requests, so `/api/v1/auth/key` is used as the canonical identity check (returning 200 for valid keys, 401 otherwise). Key resolution checks `OPENROUTER_API_KEY` via `getEnvApiKey` in `packages/ai/src/stream.ts`. diff --git a/packages/ai/src/utils/openrouter-headers.ts b/packages/ai/src/utils/openrouter-headers.ts index e374f5088..5f4ba74b8 100644 --- a/packages/ai/src/utils/openrouter-headers.ts +++ b/packages/ai/src/utils/openrouter-headers.ts @@ -2,9 +2,9 @@ import packageJson from "../../package.json" with { type: "json" }; export function getOpenRouterHeaders(): Record { return { - "User-Agent": `Oh-My-Pi/${packageJson.version}`, + "User-Agent": `omp/${packageJson.version}`, "HTTP-Referer": "https://omp.sh/", - "X-OpenRouter-Title": "Oh-My-Pi", + "X-OpenRouter-Title": "omp", "X-OpenRouter-Categories": "cli-agent", "X-OpenRouter-Cache": "true", "X-OpenRouter-Cache-TTL": "3600", diff --git a/packages/coding-agent/src/tools/image-gen.ts b/packages/coding-agent/src/tools/image-gen.ts index 5e9a289c1..360f4acbe 100644 --- a/packages/coding-agent/src/tools/image-gen.ts +++ b/packages/coding-agent/src/tools/image-gen.ts @@ -1,7 +1,7 @@ import * as os from "node:os"; import * as path from "node:path"; import { type } from "@oh-my-pi/omptype"; -import { type ApiKey, type FetchImpl, getEnvApiKey, type Model, withAuth } from "@oh-my-pi/pi-ai"; +import { type ApiKey, type FetchImpl, getEnvApiKey, getOpenRouterHeaders, type Model, withAuth } from "@oh-my-pi/pi-ai"; import { ProviderHttpError } from "@oh-my-pi/pi-ai/error"; import { CODEX_BASE_URL, @@ -1479,9 +1479,7 @@ export const imageGenTool: CustomTool { fetch: async request => { requests += 1; expect(request.headers.get("content-type")).toBe("application/json"); - expect(request.headers.get("user-agent")).toBe(`Oh-My-Pi/${packageJson.version}`); + expect(request.headers.get("user-agent")).toBe(`omp/${packageJson.version}`); expect(request.headers.get("http-referer")).toBe("https://omp.sh/"); - expect(request.headers.get("x-openrouter-title")).toBe("Oh-My-Pi"); + expect(request.headers.get("x-openrouter-title")).toBe("omp"); expect(request.headers.get("x-openrouter-categories")).toBe("cli-agent"); expect(request.headers.get("x-title")).toBeNull(); expect(request.headers.get("authorization")).toBeNull(); diff --git a/scripts/rewrite-system-prompt.ts b/scripts/rewrite-system-prompt.ts index c63b2c81d..c6a153100 100755 --- a/scripts/rewrite-system-prompt.ts +++ b/scripts/rewrite-system-prompt.ts @@ -417,7 +417,7 @@ export function makeOpenRouterRewriter(opts: OpenRouterOptions): RewriteChunk { Authorization: `Bearer ${opts.apiKey}`, "Content-Type": "application/json", "HTTP-Referer": "https://omp.sh/", - "X-Title": "Oh-My-Pi", + "X-Title": "omp", }, body, });