diff --git a/packages/types/src/provider-settings.ts b/packages/types/src/provider-settings.ts index e6b5c4ca260..beb5c879f8a 100644 --- a/packages/types/src/provider-settings.ts +++ b/packages/types/src/provider-settings.ts @@ -227,6 +227,7 @@ const unboundSchema = baseProviderSettingsSchema.extend({ const requestySchema = baseProviderSettingsSchema.extend({ requestyApiKey: z.string().optional(), requestyModelId: z.string().optional(), + requestyBaseUrl: z.string().optional(), }) const humanRelaySchema = baseProviderSettingsSchema diff --git a/src/api/providers/__tests__/requesty.spec.ts b/src/api/providers/__tests__/requesty.spec.ts index 55fb976fd1e..e647b572823 100644 --- a/src/api/providers/__tests__/requesty.spec.ts +++ b/src/api/providers/__tests__/requesty.spec.ts @@ -65,6 +65,25 @@ describe("RequestyHandler", () => { }) }) + it("initializes with custom base URL when provided", () => { + const customOptions: ApiHandlerOptions = { + ...mockOptions, + requestyBaseUrl: "https://custom.requesty.ai/v1", + } + const handler = new RequestyHandler(customOptions) + expect(handler).toBeInstanceOf(RequestyHandler) + + expect(OpenAI).toHaveBeenCalledWith({ + baseURL: "https://custom.requesty.ai/v1", + apiKey: customOptions.requestyApiKey, + defaultHeaders: { + "HTTP-Referer": "https://github.com/RooVetGit/Roo-Cline", + "X-Title": "Roo Code", + "User-Agent": `RooCode/${Package.version}`, + }, + }) + }) + describe("fetchModel", () => { it("returns correct model info when options are provided", async () => { const handler = new RequestyHandler(mockOptions) diff --git a/src/api/providers/fetchers/modelCache.ts b/src/api/providers/fetchers/modelCache.ts index a21e75ded93..b3215ed1391 100644 --- a/src/api/providers/fetchers/modelCache.ts +++ b/src/api/providers/fetchers/modelCache.ts @@ -59,7 +59,7 @@ export const getModels = async (options: GetModelsOptions): Promise break case "requesty": // Requesty models endpoint requires an API key for per-user custom policies - models = await getRequestyModels(options.apiKey) + models = await getRequestyModels(options.apiKey, options.baseUrl) break case "glama": models = await getGlamaModels() diff --git a/src/api/providers/fetchers/requesty.ts b/src/api/providers/fetchers/requesty.ts index e339dae1aa6..acdd8774d7d 100644 --- a/src/api/providers/fetchers/requesty.ts +++ b/src/api/providers/fetchers/requesty.ts @@ -4,7 +4,7 @@ import type { ModelInfo } from "@roo-code/types" import { parseApiPrice } from "../../../shared/cost" -export async function getRequestyModels(apiKey?: string): Promise> { +export async function getRequestyModels(apiKey?: string, baseUrl?: string): Promise> { const models: Record = {} try { @@ -14,7 +14,8 @@ export async function getRequestyModels(apiKey?: string): Promise = [ { key: "openrouter", options: { provider: "openrouter" } }, - { key: "requesty", options: { provider: "requesty", apiKey: apiConfiguration.requestyApiKey } }, + { + key: "requesty", + options: { + provider: "requesty", + apiKey: apiConfiguration.requestyApiKey, + baseUrl: apiConfiguration.requestyBaseUrl, + }, + }, { key: "glama", options: { provider: "glama" } }, { key: "unbound", options: { provider: "unbound", apiKey: apiConfiguration.unboundApiKey } }, ] diff --git a/src/shared/api.ts b/src/shared/api.ts index f1bf7dbaea4..2ec3da483a9 100644 --- a/src/shared/api.ts +++ b/src/shared/api.ts @@ -135,7 +135,7 @@ export const getModelMaxOutputTokens = ({ export type GetModelsOptions = | { provider: "openrouter" } | { provider: "glama" } - | { provider: "requesty"; apiKey?: string } + | { provider: "requesty"; apiKey?: string; baseUrl?: string } | { provider: "unbound"; apiKey?: string } | { provider: "litellm"; apiKey: string; baseUrl: string } | { provider: "ollama"; baseUrl?: string } diff --git a/webview-ui/src/components/settings/providers/Requesty.tsx b/webview-ui/src/components/settings/providers/Requesty.tsx index ac9e2735e96..3a43c5d15ee 100644 --- a/webview-ui/src/components/settings/providers/Requesty.tsx +++ b/webview-ui/src/components/settings/providers/Requesty.tsx @@ -1,4 +1,5 @@ import { useCallback, useState } from "react" +import { Checkbox } from "vscrui" import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react" import { type ProviderSettings, type OrganizationAllowList, requestyDefaultModelId } from "@roo-code/types" @@ -34,6 +35,7 @@ export const Requesty = ({ const { t } = useAppTranslation() const [didRefetch, setDidRefetch] = useState() + const [requestyBaseUrlSelected, setRequestyBaseUrlSelected] = useState(!!apiConfiguration?.requestyBaseUrl) const handleInputChange = useCallback( ( @@ -72,6 +74,28 @@ export const Requesty = ({ {t("settings:providers.getRequestyApiKey")} )} +
+ { + setRequestyBaseUrlSelected(checked) + + if (!checked) { + setApiConfigurationField("requestyBaseUrl", "") + } + }}> + {t("settings:providers.useCustomBaseUrl")} + + {requestyBaseUrlSelected && ( + + )} +