mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
Merge def3d0fac0 into b867ec9145
This commit is contained in:
commit
db9100e601
9 changed files with 71 additions and 13 deletions
|
|
@ -262,6 +262,26 @@ describe("getLiteLLMModels", () => {
|
|||
})
|
||||
})
|
||||
|
||||
it("makes request without authorization header when API key is undefined", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels(undefined, "http://localhost:4000")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/v1/model/info", {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles computer use models correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { DEFAULT_HEADERS } from "../constants"
|
|||
* @returns A promise that resolves to a record of model IDs to model info
|
||||
* @throws Will throw an error if the request fails or the response is not as expected.
|
||||
*/
|
||||
export async function getLiteLLMModels(apiKey: string, baseUrl: string): Promise<ModelRecord> {
|
||||
export async function getLiteLLMModels(apiKey: string | undefined, baseUrl: string): Promise<ModelRecord> {
|
||||
try {
|
||||
const headers: Record<string, string> = {
|
||||
"Content-Type": "application/json",
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ export class LiteLLMHandler extends RouterProvider implements SingleCompletionHa
|
|||
options,
|
||||
name: "litellm",
|
||||
baseURL: `${options.litellmBaseUrl || "http://localhost:4000"}`,
|
||||
apiKey: options.litellmApiKey || "dummy-key",
|
||||
apiKey: options.litellmApiKey || "",
|
||||
modelId: options.litellmModelId,
|
||||
defaultModelId: litellmDefaultModelId,
|
||||
defaultModelInfo: litellmDefaultModelInfo,
|
||||
|
|
|
|||
|
|
@ -929,20 +929,27 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|||
{ key: "vercel-ai-gateway", options: { provider: "vercel-ai-gateway" } },
|
||||
]
|
||||
|
||||
// LiteLLM is conditional on baseUrl+apiKey
|
||||
// LiteLLM is conditional on baseUrl (apiKey is optional for self-hosted instances)
|
||||
const litellmApiKey = apiConfiguration.litellmApiKey || message?.values?.litellmApiKey
|
||||
const litellmBaseUrl = apiConfiguration.litellmBaseUrl || message?.values?.litellmBaseUrl
|
||||
|
||||
if (litellmApiKey && litellmBaseUrl) {
|
||||
if (litellmBaseUrl) {
|
||||
// If explicit credentials are provided in message.values (from Refresh Models button),
|
||||
// flush the cache first to ensure we fetch fresh data with the new credentials
|
||||
if (message?.values?.litellmApiKey || message?.values?.litellmBaseUrl) {
|
||||
await flushModels({ provider: "litellm", apiKey: litellmApiKey, baseUrl: litellmBaseUrl }, true)
|
||||
await flushModels(
|
||||
{ provider: "litellm", apiKey: litellmApiKey || "", baseUrl: litellmBaseUrl },
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
candidates.push({
|
||||
key: "litellm",
|
||||
options: { provider: "litellm", apiKey: litellmApiKey, baseUrl: litellmBaseUrl },
|
||||
options: {
|
||||
provider: "litellm",
|
||||
apiKey: litellmApiKey || "",
|
||||
baseUrl: litellmBaseUrl,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -171,7 +171,7 @@ type CommonFetchParams = {
|
|||
const dynamicProviderExtras = {
|
||||
openrouter: {} as {}, // eslint-disable-line @typescript-eslint/no-empty-object-type
|
||||
"vercel-ai-gateway": {} as {}, // eslint-disable-line @typescript-eslint/no-empty-object-type
|
||||
litellm: {} as { apiKey: string; baseUrl: string },
|
||||
litellm: {} as { apiKey?: string; baseUrl: string },
|
||||
requesty: {} as { apiKey?: string; baseUrl?: string },
|
||||
unbound: {} as { apiKey?: string },
|
||||
ollama: {} as {}, // eslint-disable-line @typescript-eslint/no-empty-object-type
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export const LiteLLM = ({
|
|||
const key = apiConfiguration.litellmApiKey
|
||||
const url = apiConfiguration.litellmBaseUrl
|
||||
|
||||
if (!key || !url) {
|
||||
if (!url) {
|
||||
setRefreshStatus("error")
|
||||
setRefreshError(t("settings:providers.refreshModels.missingConfig"))
|
||||
return
|
||||
|
|
@ -121,9 +121,7 @@ export const LiteLLM = ({
|
|||
<Button
|
||||
variant="outline"
|
||||
onClick={handleRefreshModels}
|
||||
disabled={
|
||||
refreshStatus === "loading" || !apiConfiguration.litellmApiKey || !apiConfiguration.litellmBaseUrl
|
||||
}
|
||||
disabled={refreshStatus === "loading" || !apiConfiguration.litellmBaseUrl}
|
||||
className="w-full">
|
||||
<div className="flex items-center gap-2">
|
||||
{refreshStatus === "loading" ? (
|
||||
|
|
|
|||
|
|
@ -927,6 +927,7 @@
|
|||
},
|
||||
"validation": {
|
||||
"apiKey": "You must provide a valid API key.",
|
||||
"baseUrl": "You must provide a valid base URL.",
|
||||
"awsRegion": "You must choose a region to use with Amazon Bedrock.",
|
||||
"googleCloud": "You must provide a valid Google Cloud Project ID and Region.",
|
||||
"modelId": "You must provide a valid model ID.",
|
||||
|
|
|
|||
|
|
@ -158,6 +158,38 @@ describe("Model Validation Functions", () => {
|
|||
expect(result).toBeUndefined() // Should not return model validation error
|
||||
})
|
||||
|
||||
it("returns undefined for litellm with base URL but no API key", () => {
|
||||
const config: ProviderSettings = {
|
||||
apiProvider: "litellm",
|
||||
litellmBaseUrl: "http://localhost:4000",
|
||||
// No litellmApiKey - should be valid for self-hosted instances
|
||||
}
|
||||
|
||||
const result = validateApiConfigurationExcludingModelErrors(config, mockRouterModels, allowAllOrganization)
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it("returns error for litellm without base URL", () => {
|
||||
const config: ProviderSettings = {
|
||||
apiProvider: "litellm",
|
||||
// No litellmBaseUrl
|
||||
}
|
||||
|
||||
const result = validateApiConfigurationExcludingModelErrors(config, mockRouterModels, allowAllOrganization)
|
||||
expect(result).toBe("settings:validation.baseUrl")
|
||||
})
|
||||
|
||||
it("returns undefined for litellm with both base URL and API key", () => {
|
||||
const config: ProviderSettings = {
|
||||
apiProvider: "litellm",
|
||||
litellmBaseUrl: "http://localhost:4000",
|
||||
litellmApiKey: "some-key",
|
||||
}
|
||||
|
||||
const result = validateApiConfigurationExcludingModelErrors(config, mockRouterModels, allowAllOrganization)
|
||||
expect(result).toBeUndefined()
|
||||
})
|
||||
|
||||
it("excludes model-specific organization errors", () => {
|
||||
const config: ProviderSettings = {
|
||||
apiProvider: "openrouter",
|
||||
|
|
|
|||
|
|
@ -54,8 +54,8 @@ function validateModelsAndKeysProvided(apiConfiguration: ProviderSettings): stri
|
|||
}
|
||||
break
|
||||
case "litellm":
|
||||
if (!apiConfiguration.litellmApiKey) {
|
||||
return i18next.t("settings:validation.apiKey")
|
||||
if (!apiConfiguration.litellmBaseUrl) {
|
||||
return i18next.t("settings:validation.baseUrl")
|
||||
}
|
||||
break
|
||||
case "anthropic":
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue