Fix BYOK endpoint URL: accept full chat-completions URLs, not just base URLs
The OpenAI-compatible adapter unconditionally appended /v1/chat/completions to the configured endpoint, so a BYOK config whose endpoint is the full gateway URL (e.g. https://host/v1/chat/completions) produced a doubled path and failed. ResolveChatUrl now uses the URL as-is when it already targets /chat/completions, appends /chat/completions to a base ending in /v1, and otherwise appends /v1/chat/completions. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -50,8 +50,7 @@ internal sealed class OpenAiCompatibleModelClient(HttpClient http) : IModelClien
|
|||||||
var stopwatch = Stopwatch.StartNew();
|
var stopwatch = Stopwatch.StartNew();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var baseUrl = (request.Endpoint ?? "https://api.openai.com").TrimEnd('/');
|
using var message = new HttpRequestMessage(HttpMethod.Post, ResolveChatUrl(request.Endpoint));
|
||||||
using var message = new HttpRequestMessage(HttpMethod.Post, $"{baseUrl}/v1/chat/completions");
|
|
||||||
if (!string.IsNullOrEmpty(request.ApiKey))
|
if (!string.IsNullOrEmpty(request.ApiKey))
|
||||||
{
|
{
|
||||||
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", request.ApiKey);
|
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", request.ApiKey);
|
||||||
@@ -110,6 +109,24 @@ internal sealed class OpenAiCompatibleModelClient(HttpClient http) : IModelClien
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resolve the chat-completions URL from a BYOK endpoint. Accepts a base URL (we append the path),
|
||||||
|
/// a base already ending in <c>/v1</c>, or the full <c>…/chat/completions</c> URL pasted as-is — so
|
||||||
|
/// a user who enters the complete gateway URL doesn't get a doubled path.
|
||||||
|
/// </summary>
|
||||||
|
private static string ResolveChatUrl(string? endpoint)
|
||||||
|
{
|
||||||
|
var url = (endpoint ?? "https://api.openai.com").Trim().TrimEnd('/');
|
||||||
|
if (url.Contains("/chat/completions", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.EndsWith("/v1", StringComparison.OrdinalIgnoreCase)
|
||||||
|
? $"{url}/chat/completions"
|
||||||
|
: $"{url}/v1/chat/completions";
|
||||||
|
}
|
||||||
|
|
||||||
private static object[] BuildMessages(ModelRequest request)
|
private static object[] BuildMessages(ModelRequest request)
|
||||||
{
|
{
|
||||||
if (request.Messages is not { Count: > 0 })
|
if (request.Messages is not { Count: > 0 })
|
||||||
|
|||||||
Reference in New Issue
Block a user