Skip to content

Commit f0aa301

Browse files
committed
feat: add custom URL option for Requesty provider
- Add requestyBaseUrl field to provider settings schema - Update RequestyHandler to use custom base URL when provided - Update fetcher functions to support custom base URL parameter - Add UI checkbox and text field for custom URL configuration - Update webview message handler to pass base URL to model fetcher - Add tests for custom base URL functionality Fixes #6983
1 parent 12d1959 commit f0aa301

File tree

8 files changed

+63
-7
lines changed

8 files changed

+63
-7
lines changed

packages/types/src/provider-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@ const unboundSchema = baseProviderSettingsSchema.extend({
227227
const requestySchema = baseProviderSettingsSchema.extend({
228228
requestyApiKey: z.string().optional(),
229229
requestyModelId: z.string().optional(),
230+
requestyBaseUrl: z.string().optional(),
230231
})
231232

232233
const humanRelaySchema = baseProviderSettingsSchema

src/api/providers/__tests__/requesty.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,25 @@ describe("RequestyHandler", () => {
6565
})
6666
})
6767

68+
it("initializes with custom base URL when provided", () => {
69+
const customOptions: ApiHandlerOptions = {
70+
...mockOptions,
71+
requestyBaseUrl: "https://custom.requesty.ai/v1",
72+
}
73+
const handler = new RequestyHandler(customOptions)
74+
expect(handler).toBeInstanceOf(RequestyHandler)
75+
76+
expect(OpenAI).toHaveBeenCalledWith({
77+
baseURL: "https://custom.requesty.ai/v1",
78+
apiKey: customOptions.requestyApiKey,
79+
defaultHeaders: {
80+
"HTTP-Referer": "https://github.com/RooVetGit/Roo-Cline",
81+
"X-Title": "Roo Code",
82+
"User-Agent": `RooCode/${Package.version}`,
83+
},
84+
})
85+
})
86+
6887
describe("fetchModel", () => {
6988
it("returns correct model info when options are provided", async () => {
7089
const handler = new RequestyHandler(mockOptions)

src/api/providers/fetchers/modelCache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const getModels = async (options: GetModelsOptions): Promise<ModelRecord>
5959
break
6060
case "requesty":
6161
// Requesty models endpoint requires an API key for per-user custom policies
62-
models = await getRequestyModels(options.apiKey)
62+
models = await getRequestyModels(options.apiKey, options.baseUrl)
6363
break
6464
case "glama":
6565
models = await getGlamaModels()

src/api/providers/fetchers/requesty.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { ModelInfo } from "@roo-code/types"
44

55
import { parseApiPrice } from "../../../shared/cost"
66

7-
export async function getRequestyModels(apiKey?: string): Promise<Record<string, ModelInfo>> {
7+
export async function getRequestyModels(apiKey?: string, baseUrl?: string): Promise<Record<string, ModelInfo>> {
88
const models: Record<string, ModelInfo> = {}
99

1010
try {
@@ -14,7 +14,8 @@ export async function getRequestyModels(apiKey?: string): Promise<Record<string,
1414
headers["Authorization"] = `Bearer ${apiKey}`
1515
}
1616

17-
const url = "https://router.requesty.ai/v1/models"
17+
const apiBaseUrl = baseUrl || "https://router.requesty.ai/v1"
18+
const url = `${apiBaseUrl}/models`
1819
const response = await axios.get(url, { headers })
1920
const rawModels = response.data.data
2021

src/api/providers/requesty.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,18 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan
4747
this.options = options
4848

4949
this.client = new OpenAI({
50-
baseURL: "https://router.requesty.ai/v1",
50+
baseURL: this.options.requestyBaseUrl || "https://router.requesty.ai/v1",
5151
apiKey: this.options.requestyApiKey ?? "not-provided",
5252
defaultHeaders: DEFAULT_HEADERS,
5353
})
5454
}
5555

5656
public async fetchModel() {
57-
this.models = await getModels({ provider: "requesty" })
57+
this.models = await getModels({
58+
provider: "requesty",
59+
apiKey: this.options.requestyApiKey,
60+
baseUrl: this.options.requestyBaseUrl,
61+
})
5862
return this.getModel()
5963
}
6064

src/core/webview/webviewMessageHandler.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,14 @@ export const webviewMessageHandler = async (
543543

544544
const modelFetchPromises: Array<{ key: RouterName; options: GetModelsOptions }> = [
545545
{ key: "openrouter", options: { provider: "openrouter" } },
546-
{ key: "requesty", options: { provider: "requesty", apiKey: apiConfiguration.requestyApiKey } },
546+
{
547+
key: "requesty",
548+
options: {
549+
provider: "requesty",
550+
apiKey: apiConfiguration.requestyApiKey,
551+
baseUrl: apiConfiguration.requestyBaseUrl,
552+
},
553+
},
547554
{ key: "glama", options: { provider: "glama" } },
548555
{ key: "unbound", options: { provider: "unbound", apiKey: apiConfiguration.unboundApiKey } },
549556
]

src/shared/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export const getModelMaxOutputTokens = ({
135135
export type GetModelsOptions =
136136
| { provider: "openrouter" }
137137
| { provider: "glama" }
138-
| { provider: "requesty"; apiKey?: string }
138+
| { provider: "requesty"; apiKey?: string; baseUrl?: string }
139139
| { provider: "unbound"; apiKey?: string }
140140
| { provider: "litellm"; apiKey: string; baseUrl: string }
141141
| { provider: "ollama"; baseUrl?: string }

webview-ui/src/components/settings/providers/Requesty.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useCallback, useState } from "react"
2+
import { Checkbox } from "vscrui"
23
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
34

45
import { type ProviderSettings, type OrganizationAllowList, requestyDefaultModelId } from "@roo-code/types"
@@ -34,6 +35,7 @@ export const Requesty = ({
3435
const { t } = useAppTranslation()
3536

3637
const [didRefetch, setDidRefetch] = useState<boolean>()
38+
const [requestyBaseUrlSelected, setRequestyBaseUrlSelected] = useState(!!apiConfiguration?.requestyBaseUrl)
3739

3840
const handleInputChange = useCallback(
3941
<K extends keyof ProviderSettings, E>(
@@ -72,6 +74,28 @@ export const Requesty = ({
7274
{t("settings:providers.getRequestyApiKey")}
7375
</VSCodeButtonLink>
7476
)}
77+
<div>
78+
<Checkbox
79+
checked={requestyBaseUrlSelected}
80+
onChange={(checked: boolean) => {
81+
setRequestyBaseUrlSelected(checked)
82+
83+
if (!checked) {
84+
setApiConfigurationField("requestyBaseUrl", "")
85+
}
86+
}}>
87+
{t("settings:providers.useCustomBaseUrl")}
88+
</Checkbox>
89+
{requestyBaseUrlSelected && (
90+
<VSCodeTextField
91+
value={apiConfiguration?.requestyBaseUrl || ""}
92+
type="url"
93+
onInput={handleInputChange("requestyBaseUrl")}
94+
placeholder="Default: https://router.requesty.ai/v1"
95+
className="w-full mt-1"
96+
/>
97+
)}
98+
</div>
7599
<Button
76100
variant="outline"
77101
onClick={() => {

0 commit comments

Comments
 (0)