Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,32 @@ describe('ProviderClient', () => {
expect(sentBody.stream).toBe(false);
});

it('preserves vendor/path model ids for custom endpoints (no prefix stripping)', async () => {
mockFetch.mockResolvedValue(new Response('{}', { status: 200 }));

const customEndpoint = {
baseUrl: 'http://localhost:8000',
buildHeaders: (key: string) => ({
Authorization: `Bearer ${key}`,
'Content-Type': 'application/json',
}),
buildPath: () => '/v1/chat/completions',
format: 'openai' as const,
};

await client.forward({
provider: 'custom:uuid',
apiKey: 'k',
model: 'z-ai/step-3.5-flash',
body,
stream: false,
customEndpoint,
});

const sentBody = JSON.parse(mockFetch.mock.calls[0][1].body);
expect(sentBody.model).toBe('z-ai/step-3.5-flash');
});

it('uses custom endpoint with streaming', async () => {
mockFetch.mockResolvedValue(new Response('{}', { status: 200 }));

Expand Down
6 changes: 4 additions & 2 deletions packages/backend/src/routing/proxy/provider-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ const PROVIDER_TIMEOUT_MS = 180_000;
* Models synced from OpenRouter use vendor prefixes, but native APIs expect bare names.
*/
function stripModelPrefix(model: string, endpointKey: string): string {
// OpenRouter accepts and expects vendor prefixes
if (endpointKey === 'openrouter') return model;
// OpenRouter accepts and expects vendor prefixes.
// Custom HTTP gateways store arbitrary upstream model ids (e.g. "z-ai/step-3.5-flash");
// stripping the first path segment breaks those backends.
if (endpointKey === 'openrouter' || endpointKey === 'custom') return model;
const slashIdx = model.indexOf('/');
return slashIdx > 0 ? model.substring(slashIdx + 1) : model;
}
Expand Down