refactor(ai): rebranded openrouter identifiers and user agent to omp
- Updated user agent and openrouter titles in packages/ai from Oh-My-Pi to omp. - Integrated getOpenRouterHeaders into image generation tool requests in packages/coding-agent. - Updated provider documentation and test assertions to reflect the rebrand.
This commit is contained in:
@@ -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/<ver>`, `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/<ver>`, `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`.
|
||||
|
||||
@@ -2,9 +2,9 @@ import packageJson from "../../package.json" with { type: "json" };
|
||||
|
||||
export function getOpenRouterHeaders(): Record<string, string> {
|
||||
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",
|
||||
|
||||
@@ -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<typeof imageGenSchema, ImageGenToolDetails
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${key}`,
|
||||
"HTTP-Referer": "https://omp.sh/",
|
||||
"X-OpenRouter-Title": "Oh-My-Pi",
|
||||
"X-OpenRouter-Categories": "cli-agent",
|
||||
...getOpenRouterHeaders(),
|
||||
},
|
||||
body: JSON.stringify(requestBody),
|
||||
signal: requestSignal,
|
||||
|
||||
@@ -133,9 +133,9 @@ describe("optional embeddings", () => {
|
||||
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();
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user