diff --git a/src/components/ui/provider-brand-icon.tsx b/src/components/ui/provider-brand-icon.tsx
index bd3bb4518..65f85cd05 100644
--- a/src/components/ui/provider-brand-icon.tsx
+++ b/src/components/ui/provider-brand-icon.tsx
@@ -37,6 +37,9 @@ interface ProviderBrandIconByKeyProps {
export function ProviderBrandIconByKey({ iconKey: key, size = 18 }: ProviderBrandIconByKeyProps) {
if (key === 'tokendance') return ;
if (key === 'openrouter') return ;
+ // Requesty has no @lobehub/icons entry yet; render its logo from models.dev
+ // the same way ModelSelectorLogo already does for the `requesty` provider.
+ if (key === 'requesty') return
;
if (key === 'zhipu') return ;
if (key === 'kimi') return ;
if (key === 'moonshot') return ;
diff --git a/src/lib/provider-catalog.ts b/src/lib/provider-catalog.ts
index bbe88f483..62637e352 100644
--- a/src/lib/provider-catalog.ts
+++ b/src/lib/provider-catalog.ts
@@ -866,6 +866,46 @@ export const VENDOR_PRESETS: VendorPreset[] = [
},
},
+ // ── Requesty ──
+ // Requesty is an OpenAI-compatible model router (like OpenRouter, but its
+ // gateway speaks the OpenAI Chat Completions wire protocol at
+ // `https://router.requesty.ai/v1`). It therefore rides the generic
+ // `openai-compatible` path (CodePilot / Codex runtimes via the AI SDK chat
+ // transport) rather than OpenRouter's Anthropic-skin `protocol: 'openrouter'`.
+ // Because the base URL ends in `/v1` and the preset is not catalog-only, the
+ // "搜索并添加模型" dialog reaches Requesty's `/v1/models` through the generic
+ // reliable-provider probe (canReliablyFetchModels / canSearchUpstreamModels),
+ // so no dedicated catalog fetcher is needed. `provider/model` naming matches
+ // OpenRouter. `defaultModels` is an intentional alias-only bootstrap (a few
+ // popular SKUs); user-added models are normal usage, not drift, so no
+ // `fixedCatalog`/`modelDiscoveryMode` gate.
+ {
+ key: 'requesty',
+ name: 'Requesty',
+ description: 'Use Requesty to access multiple models',
+ descriptionZh: '通过 Requesty 访问多种模型',
+ protocol: 'openai-compatible',
+ authStyle: 'api_key',
+ baseUrl: 'https://router.requesty.ai/v1',
+ defaultEnvOverrides: {},
+ defaultModels: [
+ { modelId: 'openai/gpt-4o-mini', displayName: 'GPT-4o mini', role: 'default', capabilities: { toolUse: true, vision: true } },
+ { modelId: 'openai/gpt-4o', displayName: 'GPT-4o', capabilities: { toolUse: true, vision: true } },
+ { modelId: 'anthropic/claude-sonnet-4-5', displayName: 'Claude Sonnet 4.5', capabilities: { toolUse: true, vision: true, reasoning: true } },
+ { modelId: 'google/gemini-2.5-flash', displayName: 'Gemini 2.5 Flash', capabilities: { toolUse: true, vision: true } },
+ { modelId: 'deepseek/deepseek-chat', displayName: 'DeepSeek Chat', capabilities: { toolUse: true } },
+ ],
+ defaultRoleModels: { default: 'openai/gpt-4o-mini' },
+ fields: ['api_key'],
+ iconKey: 'requesty',
+ meta: {
+ apiKeyUrl: 'https://app.requesty.ai/api-keys',
+ docsUrl: 'https://docs.requesty.ai',
+ pricingUrl: 'https://app.requesty.ai/model-library',
+ billingModel: 'pay_as_you_go',
+ },
+ },
+
// ── Zhipu GLM (China) ──
{
key: 'glm-cn',
diff --git a/src/lib/provider-icon-rule.ts b/src/lib/provider-icon-rule.ts
index 75f227541..35473d218 100644
--- a/src/lib/provider-icon-rule.ts
+++ b/src/lib/provider-icon-rule.ts
@@ -18,6 +18,7 @@ import { isTokenDanceBaseUrl } from "./tokendance";
export type ProviderIconKey =
| "tokendance"
| "openrouter"
+ | "requesty"
| "zhipu"
| "kimi"
| "moonshot"
@@ -45,6 +46,10 @@ export function getProviderIconKey(name: string, baseUrl: string): ProviderIconK
if (isTokenDanceBaseUrl(baseUrl) || lower.includes("tokendance") || lower.includes("词元跳动")) return "tokendance";
if (lower.includes("openrouter")) return "openrouter";
+ // Requesty: OpenAI-compatible model router. Scoped to brand-unique
+ // fragments (`requesty.ai` host / `requesty` name) so it can't steal
+ // another vendor's icon.
+ if (url.includes("requesty.ai") || lower.includes("requesty")) return "requesty";
// OpenCode Go: the provider name carries a protocol suffix — "OpenCode Go
// (OpenAI)" / "(Anthropic)". Match BEFORE the openai / anthropic name
// matchers below, which would otherwise steal the wrong brand logo