mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-10 22:41:14 +00:00
fix(litellm): handle baseurl with paths correctly (#5697)
Co-authored-by: Daniel Riccio <ricciodaniel98@gmail.com>
This commit is contained in:
parent
d0452d0d5c
commit
9b6fb36d6f
2 changed files with 131 additions and 1 deletions
|
|
@ -39,6 +39,132 @@ describe("getLiteLLMModels", () => {
|
|||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with a path correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000/litellm")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/litellm/v1/model/info", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with a path and trailing slash correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000/litellm/")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/litellm/v1/model/info", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with double slashes correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000/litellm//")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/litellm/v1/model/info", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with query parameters correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000/litellm?key=value")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/litellm/v1/model/info?key=value", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with fragments correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000/litellm#section")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/litellm/v1/model/info#section", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("handles base URLs with port and no path correctly", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
data: [],
|
||||
},
|
||||
}
|
||||
|
||||
mockedAxios.get.mockResolvedValue(mockResponse)
|
||||
|
||||
await getLiteLLMModels("test-api-key", "http://localhost:4000")
|
||||
|
||||
expect(mockedAxios.get).toHaveBeenCalledWith("http://localhost:4000/v1/model/info", {
|
||||
headers: {
|
||||
Authorization: "Bearer test-api-key",
|
||||
"Content-Type": "application/json",
|
||||
...DEFAULT_HEADERS,
|
||||
},
|
||||
timeout: 5000,
|
||||
})
|
||||
})
|
||||
|
||||
it("successfully fetches and formats LiteLLM models", async () => {
|
||||
const mockResponse = {
|
||||
data: {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,11 @@ export async function getLiteLLMModels(apiKey: string, baseUrl: string): Promise
|
|||
headers["Authorization"] = `Bearer ${apiKey}`
|
||||
}
|
||||
// Use URL constructor to properly join base URL and path
|
||||
const url = new URL("/v1/model/info", baseUrl).href
|
||||
// This approach handles all edge cases including paths, query params, and fragments
|
||||
const urlObj = new URL(baseUrl)
|
||||
// Normalize the pathname by removing trailing slashes and multiple slashes
|
||||
urlObj.pathname = urlObj.pathname.replace(/\/+$/, "").replace(/\/+/g, "/") + "/v1/model/info"
|
||||
const url = urlObj.href
|
||||
// Added timeout to prevent indefinite hanging
|
||||
const response = await axios.get(url, { headers, timeout: 5000 })
|
||||
const models: ModelRecord = {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue