fix: use provider node credentials for embeddings

This commit is contained in:
jacob2826 2026-03-22 16:22:58 +08:00
parent bf3f64bea4
commit ecccce86e4
3 changed files with 61 additions and 1 deletions

View file

@ -17,6 +17,7 @@ export interface EmbeddingProvider {
}
export interface EmbeddingProviderNodeRow {
id?: string;
prefix: string;
name: string;
baseUrl: string;

View file

@ -160,6 +160,7 @@ export async function POST(request) {
// Resolve provider config — dynamic first (local override), then hardcoded
let providerConfig: EmbeddingProvider | null =
dynamicProviders.find((dp) => dp.id === provider) || getEmbeddingProvider(provider) || null;
let credentialsProviderId = provider;
// #496: Fallback — resolve from ALL provider_nodes (not just localhost)
// This enables custom embedding models (e.g. google/gemini-embedding-001) whose
@ -180,6 +181,7 @@ export async function POST(request) {
authHeader: "bearer",
models: [],
};
credentialsProviderId = matchingNode.id || provider;
log.info(
"EMBED",
`Resolved custom embedding provider: ${provider}${providerConfig.baseUrl}`
@ -200,7 +202,7 @@ export async function POST(request) {
// Get credentials — skip for local providers (authType: "none")
let credentials = null;
if (providerConfig && providerConfig.authType !== "none") {
credentials = await getProviderCredentials(provider);
credentials = await getProviderCredentials(credentialsProviderId);
if (!credentials) {
return errorResponse(
HTTP_STATUS.BAD_REQUEST,

View file

@ -106,3 +106,60 @@ test("embeddings route clears stale provider error metadata on success", async (
globalThis.fetch = originalFetch;
}
});
test("embeddings route uses provider node id for compatible provider credentials", async () => {
await resetStorage();
const providerNode = await providersDb.createProviderNode({
id: "openai-compatible-responses-google-embeddings",
type: "openai-compatible",
name: "Gemini Embeddings",
prefix: "google",
apiType: "responses",
baseUrl: "https://generativelanguage.googleapis.com/v1beta/openai",
});
const created = await providersDb.createProviderConnection({
provider: providerNode.id,
authType: "apikey",
email: null,
name: "google-compatible-key",
apiKey: "google-compatible-test-key",
testStatus: "active",
lastError: null,
lastErrorType: "token_refresh_failed",
lastErrorSource: "oauth",
errorCode: "refresh_failed",
rateLimitedUntil: null,
backoffLevel: 2,
});
const originalFetch = globalThis.fetch;
globalThis.fetch = async (url, init) => {
assert.equal(url, "https://generativelanguage.googleapis.com/v1beta/openai/embeddings");
assert.equal(init?.headers?.Authorization, "Bearer google-compatible-test-key");
return Response.json({
data: [{ object: "embedding", index: 0, embedding: [0.1, 0.2] }],
usage: { prompt_tokens: 3, total_tokens: 3 },
});
};
try {
const request = new Request("http://localhost/v1/embeddings", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ model: "google/gemini-embedding-001", input: "hello" }),
});
const response = await embeddingsRoute.POST(request);
assert.equal(response.status, 200);
const updated = await readConnection(created.id);
assert.equal(updated.testStatus, "active");
assert.equal(updated.errorCode, undefined);
assert.equal(updated.lastErrorType, undefined);
assert.equal(updated.lastErrorSource, undefined);
} finally {
globalThis.fetch = originalFetch;
}
});