Skip to content

Commit 9314316

Browse files
committed
fix: use custom base URL for all Requesty requests
- Update OAuth URL generation to use custom base URL when provided - Fix API key button to use custom base URL for web interface - Update API key info endpoint to use custom base URL - Fix models endpoint to use custom base URL - Pass requestyBaseUrl through all necessary contexts Fixes #7274
1 parent 6fd261d commit 9314316

File tree

10 files changed

+64
-19
lines changed

10 files changed

+64
-19
lines changed

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: 4 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,9 @@ 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+
// Use the base URL if provided, otherwise default to the router endpoint
18+
const apiUrl = baseUrl ? baseUrl.replace(/\/$/, "") : "https://router.requesty.ai"
19+
const url = `${apiUrl}/v1/models`
1820
const response = await axios.get(url, { headers })
1921
const rawModels = response.data.data
2022

src/api/providers/requesty.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ export class RequestyHandler extends BaseProvider implements SingleCompletionHan
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
@@ -548,7 +548,14 @@ export const webviewMessageHandler = async (
548548

549549
const modelFetchPromises: Array<{ key: RouterName; options: GetModelsOptions }> = [
550550
{ key: "openrouter", options: { provider: "openrouter" } },
551-
{ key: "requesty", options: { provider: "requesty", apiKey: apiConfiguration.requestyApiKey } },
551+
{
552+
key: "requesty",
553+
options: {
554+
provider: "requesty",
555+
apiKey: apiConfiguration.requestyApiKey,
556+
baseUrl: apiConfiguration.requestyBaseUrl,
557+
},
558+
},
552559
{ key: "glama", options: { provider: "glama" } },
553560
{ key: "unbound", options: { provider: "unbound", apiKey: apiConfiguration.unboundApiKey } },
554561
]

src/shared/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ export const getModelMaxOutputTokens = ({
145145
export type GetModelsOptions =
146146
| { provider: "openrouter" }
147147
| { provider: "glama" }
148-
| { provider: "requesty"; apiKey?: string }
148+
| { provider: "requesty"; apiKey?: string; baseUrl?: string }
149149
| { provider: "unbound"; apiKey?: string }
150150
| { provider: "litellm"; apiKey: string; baseUrl: string }
151151
| { provider: "ollama"; baseUrl?: string }

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ export const Requesty = ({
6565
<div className="flex justify-between items-center mb-1">
6666
<label className="block font-medium">{t("settings:providers.requestyApiKey")}</label>
6767
{apiConfiguration?.requestyApiKey && (
68-
<RequestyBalanceDisplay apiKey={apiConfiguration.requestyApiKey} />
68+
<RequestyBalanceDisplay
69+
apiKey={apiConfiguration.requestyApiKey}
70+
baseUrl={apiConfiguration?.requestyBaseUrl}
71+
/>
6972
)}
7073
</div>
7174
</VSCodeTextField>
@@ -74,7 +77,16 @@ export const Requesty = ({
7477
</div>
7578
{!apiConfiguration?.requestyApiKey && (
7679
<VSCodeButtonLink
77-
href="https://app.requesty.ai/api-keys"
80+
href={(() => {
81+
const baseUrl = apiConfiguration?.requestyBaseUrl || "https://app.requesty.ai"
82+
// Remove trailing slash if present and ensure we're using the app subdomain
83+
const cleanBaseUrl = baseUrl.replace(/\/$/, "")
84+
// If the base URL contains 'router' or 'api', replace with 'app' for web interface
85+
const appUrl = cleanBaseUrl
86+
.replace(/router\.requesty/, "app.requesty")
87+
.replace(/api\.requesty/, "app.requesty")
88+
return `${appUrl}/api-keys`
89+
})()}
7890
style={{ width: "100%" }}
7991
appearance="primary">
8092
{t("settings:providers.getRequestyApiKey")}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
22

33
import { useRequestyKeyInfo } from "@/components/ui/hooks/useRequestyKeyInfo"
44

5-
export const RequestyBalanceDisplay = ({ apiKey }: { apiKey: string }) => {
6-
const { data: keyInfo } = useRequestyKeyInfo(apiKey)
5+
export const RequestyBalanceDisplay = ({ apiKey, baseUrl }: { apiKey: string; baseUrl?: string }) => {
6+
const { data: keyInfo } = useRequestyKeyInfo(apiKey, baseUrl)
77

88
if (!keyInfo) {
99
return null
@@ -13,8 +13,18 @@ export const RequestyBalanceDisplay = ({ apiKey }: { apiKey: string }) => {
1313
const balance = parseFloat(keyInfo.org_balance)
1414
const formattedBalance = balance.toFixed(2)
1515

16+
// Use the base URL if provided, otherwise default to the standard app URL
17+
const settingsUrl = (() => {
18+
const appUrl = baseUrl || "https://app.requesty.ai"
19+
// Remove trailing slash if present and ensure we're using the app subdomain
20+
const cleanUrl = appUrl.replace(/\/$/, "")
21+
// If the base URL contains 'router' or 'api', replace with 'app' for web interface
22+
const webUrl = cleanUrl.replace(/router\.requesty/, "app.requesty").replace(/api\.requesty/, "app.requesty")
23+
return `${webUrl}/settings`
24+
})()
25+
1626
return (
17-
<VSCodeLink href="https://app.requesty.ai/settings" className="text-vscode-foreground hover:underline">
27+
<VSCodeLink href={settingsUrl} className="text-vscode-foreground hover:underline">
1828
${formattedBalance}
1929
</VSCodeLink>
2030
)

webview-ui/src/components/ui/hooks/useRequestyKeyInfo.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,16 @@ const requestyKeyInfoSchema = z.object({
1414

1515
export type RequestyKeyInfo = z.infer<typeof requestyKeyInfoSchema>
1616

17-
async function getRequestyKeyInfo(apiKey?: string) {
17+
async function getRequestyKeyInfo(apiKey?: string, baseUrl?: string) {
1818
if (!apiKey) return null
1919

2020
try {
21-
const response = await axios.get("https://api.requesty.ai/x/apikey", {
21+
// Use the base URL if provided, otherwise default to the standard API endpoint
22+
const apiUrl = baseUrl ? baseUrl.replace(/\/$/, "") : "https://api.requesty.ai"
23+
// Convert router.requesty.ai to api.requesty.ai for API calls
24+
const cleanApiUrl = apiUrl.replace(/router\.requesty/, "api.requesty").replace(/app\.requesty/, "api.requesty")
25+
26+
const response = await axios.get(`${cleanApiUrl}/x/apikey`, {
2227
headers: {
2328
Authorization: `Bearer ${apiKey}`,
2429
"Content-Type": "application/json",
@@ -39,10 +44,10 @@ async function getRequestyKeyInfo(apiKey?: string) {
3944
}
4045

4146
type UseRequestyKeyInfoOptions = Omit<UseQueryOptions<RequestyKeyInfo | null>, "queryKey" | "queryFn">
42-
export const useRequestyKeyInfo = (apiKey?: string, options?: UseRequestyKeyInfoOptions) => {
47+
export const useRequestyKeyInfo = (apiKey?: string, baseUrl?: string, options?: UseRequestyKeyInfoOptions) => {
4348
return useQuery<RequestyKeyInfo | null>({
44-
queryKey: ["requesty-key-info", apiKey],
45-
queryFn: () => getRequestyKeyInfo(apiKey),
49+
queryKey: ["requesty-key-info", apiKey, baseUrl],
50+
queryFn: () => getRequestyKeyInfo(apiKey, baseUrl),
4651
staleTime: 30 * 1000, // 30 seconds
4752
enabled: !!apiKey,
4853
...options,

webview-ui/src/components/welcome/WelcomeView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ const WelcomeView = () => {
7575
name: "Requesty",
7676
description: t("welcome:routers.requesty.description"),
7777
incentive: t("welcome:routers.requesty.incentive"),
78-
authUrl: getRequestyAuthUrl(uriScheme),
78+
authUrl: getRequestyAuthUrl(uriScheme, apiConfiguration?.requestyBaseUrl),
7979
},
8080
{
8181
slug: "openrouter",

webview-ui/src/oauth/urls.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ export function getOpenRouterAuthUrl(uriScheme?: string) {
1212
return `https://openrouter.ai/auth?callback_url=${getCallbackUrl("openrouter", uriScheme)}`
1313
}
1414

15-
export function getRequestyAuthUrl(uriScheme?: string) {
16-
return `https://app.requesty.ai/oauth/authorize?callback_url=${getCallbackUrl("requesty", uriScheme)}`
15+
export function getRequestyAuthUrl(uriScheme?: string, baseUrl?: string) {
16+
const requestyBaseUrl = baseUrl || "https://app.requesty.ai"
17+
// Remove trailing slash if present and ensure we're using the app subdomain for OAuth
18+
const cleanBaseUrl = requestyBaseUrl.replace(/\/$/, "")
19+
// If the base URL contains 'router' or 'api', replace with 'app' for OAuth
20+
const oauthUrl = cleanBaseUrl.replace(/router\.requesty/, "app.requesty").replace(/api\.requesty/, "app.requesty")
21+
return `${oauthUrl}/oauth/authorize?callback_url=${getCallbackUrl("requesty", uriScheme)}`
1722
}

0 commit comments

Comments
 (0)