📨 feat: Pass Custom Headers to Model Discovery (v1/models) (#10564)

This commit is contained in:
Anthony Quéré 2025-11-19 14:49:51 +01:00 committed by GitHub
parent ce1812b7c2
commit 69c6d023e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 125 additions and 1 deletions

View file

@ -80,7 +80,9 @@ const fetchModels = async ({
try {
const options = {
headers: {},
headers: {
...(headers ?? {}),
},
timeout: 5000,
};

View file

@ -81,6 +81,70 @@ describe('fetchModels', () => {
);
});
it('should pass custom headers to the API request', async () => {
const customHeaders = {
'X-Custom-Header': 'custom-value',
'X-API-Version': 'v2',
};
await fetchModels({
user: 'user123',
apiKey: 'testApiKey',
baseURL: 'https://api.test.com',
name: 'TestAPI',
headers: customHeaders,
});
expect(axios.get).toHaveBeenCalledWith(
expect.stringContaining('https://api.test.com/models'),
expect.objectContaining({
headers: expect.objectContaining({
'X-Custom-Header': 'custom-value',
'X-API-Version': 'v2',
Authorization: 'Bearer testApiKey',
}),
}),
);
});
it('should handle null headers gracefully', async () => {
await fetchModels({
user: 'user123',
apiKey: 'testApiKey',
baseURL: 'https://api.test.com',
name: 'TestAPI',
headers: null,
});
expect(axios.get).toHaveBeenCalledWith(
expect.stringContaining('https://api.test.com/models'),
expect.objectContaining({
headers: expect.objectContaining({
Authorization: 'Bearer testApiKey',
}),
}),
);
});
it('should handle undefined headers gracefully', async () => {
await fetchModels({
user: 'user123',
apiKey: 'testApiKey',
baseURL: 'https://api.test.com',
name: 'TestAPI',
headers: undefined,
});
expect(axios.get).toHaveBeenCalledWith(
expect.stringContaining('https://api.test.com/models'),
expect.objectContaining({
headers: expect.objectContaining({
Authorization: 'Bearer testApiKey',
}),
}),
);
});
afterEach(() => {
jest.clearAllMocks();
});
@ -410,6 +474,64 @@ describe('getAnthropicModels', () => {
const models = await getAnthropicModels();
expect(models).toEqual(['claude-1', 'claude-2']);
});
it('should use Anthropic-specific headers when fetching models', async () => {
delete process.env.ANTHROPIC_MODELS;
process.env.ANTHROPIC_API_KEY = 'test-anthropic-key';
axios.get.mockResolvedValue({
data: {
data: [{ id: 'claude-3' }, { id: 'claude-4' }],
},
});
await fetchModels({
user: 'user123',
apiKey: 'test-anthropic-key',
baseURL: 'https://api.anthropic.com/v1',
name: EModelEndpoint.anthropic,
});
expect(axios.get).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
headers: {
'x-api-key': 'test-anthropic-key',
'anthropic-version': expect.any(String),
},
}),
);
});
it('should pass custom headers for Anthropic endpoint', async () => {
const customHeaders = {
'X-Custom-Header': 'custom-value',
};
axios.get.mockResolvedValue({
data: {
data: [{ id: 'claude-3' }],
},
});
await fetchModels({
user: 'user123',
apiKey: 'test-anthropic-key',
baseURL: 'https://api.anthropic.com/v1',
name: EModelEndpoint.anthropic,
headers: customHeaders,
});
expect(axios.get).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
headers: {
'x-api-key': 'test-anthropic-key',
'anthropic-version': expect.any(String),
},
}),
);
});
});
describe('getGoogleModels', () => {