fix(embedding): respect requireApiKey flag in OpenAI-compatible embedding factory (#171)

Closes #167

EmbeddingModelFactory.buildOpenAi() hard-failed on any provider whose API
key was empty or unusable, so keyless providers like Ollama and OpenCode
(declared with requireApiKey=false) could pass the chat connectivity test
but bounce when the same provider's embedding model was tested.

Mirror the chat path in OpenAiCompatibleChatModelBuilder.buildOpenAiApi:

- If requireApiKey is not explicitly false, an unusable key still throws.
- If requireApiKey == false, the key check is skipped and an empty string
  is passed to OpenAiApi.builder() so no Authorization: Bearer header is
  attached to the outgoing request.
This commit is contained in:
倪程伟 2026-05-20 09:25:16 +08:00 committed by GitHub
parent 8e00613e69
commit e0f66eef25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -165,7 +165,11 @@ public class EmbeddingModelFactory {
"Provider '" + provider.getProviderId() + "' 未完成配置(缺少 API Key 或 Base URL");
}
String apiKey = provider.getApiKey();
if (!providerService.hasUsableApiKey(apiKey)) {
// Mirror the chat model builder: only require an API key when the provider row says so.
// Keyless providers (requireApiKey=false, e.g. OpenCode, local Ollama) must be allowed
// through; otherwise their cloud-model connection test passes but embedding test fails.
boolean keyRequired = !Boolean.FALSE.equals(provider.getRequireApiKey());
if (keyRequired && !providerService.hasUsableApiKey(apiKey)) {
throw new MateClawException("err.embedding.openai_key_invalid",
"Provider API Key 未配置或无效: " + provider.getProviderId());
}
@ -175,10 +179,11 @@ public class EmbeddingModelFactory {
"Provider Base URL 未配置: " + provider.getProviderId());
}
String effectiveApiKey = providerService.hasUsableApiKey(apiKey) ? apiKey.trim() : "";
// 最简构造不做 chat-specific header 重写reasoning patch
OpenAiApi api = OpenAiApi.builder()
.baseUrl(baseUrl)
.apiKey(apiKey.trim())
.apiKey(effectiveApiKey)
.embeddingsPath(resolveEmbeddingsPath(baseUrl))
.build();