fix: send OpenClaw attribution to OpenAI

This commit is contained in:
Peter Steinberger
2026-04-29 13:53:56 +01:00
parent 9881a808f2
commit d1b2d81752
27 changed files with 597 additions and 68 deletions

View File

@@ -0,0 +1,29 @@
import { describe, expect, it, vi } from "vitest";
import { resolveRemoteEmbeddingBearerClient } from "./embeddings-remote-client.js";
describe("resolveRemoteEmbeddingBearerClient", () => {
it("adds OpenClaw attribution to native OpenAI embedding requests", async () => {
vi.stubEnv("OPENCLAW_VERSION", "2026.3.22");
const client = await resolveRemoteEmbeddingBearerClient({
provider: "openai",
defaultBaseUrl: "https://api.openai.com/v1",
options: {
config: { models: {} } as never,
model: "text-embedding-3-large",
remote: {
apiKey: "sk-test",
headers: {
originator: "pi",
"User-Agent": "pi",
},
},
},
});
expect(client.headers).toMatchObject({
originator: "openclaw",
version: "2026.3.22",
"User-Agent": "openclaw/2026.3.22",
});
});
});

View File

@@ -7,6 +7,26 @@ import { normalizeOptionalString } from "./string-utils.js";
export type RemoteEmbeddingProviderId = string;
function resolveOpenClawAttributionHeaders(): Record<string, string> {
const version = typeof process !== "undefined" ? process.env.OPENCLAW_VERSION?.trim() : undefined;
return {
originator: "openclaw",
...(version ? { version } : {}),
"User-Agent": version ? `openclaw/${version}` : "openclaw",
};
}
function isNativeOpenAIEmbeddingRoute(provider: string, baseUrl: string): boolean {
if (provider !== "openai") {
return false;
}
try {
return new URL(baseUrl).hostname.toLowerCase().replace(/\.+$/, "") === "api.openai.com";
} catch {
return false;
}
}
export async function resolveRemoteEmbeddingBearerClient(params: {
provider: RemoteEmbeddingProviderId;
options: EmbeddingProviderOptions;
@@ -37,5 +57,8 @@ export async function resolveRemoteEmbeddingBearerClient(params: {
Authorization: `Bearer ${apiKey}`,
...headerOverrides,
};
if (isNativeOpenAIEmbeddingRoute(params.provider, baseUrl)) {
Object.assign(headers, resolveOpenClawAttributionHeaders());
}
return { baseUrl, headers, ssrfPolicy: buildRemoteBaseUrlPolicy(baseUrl) };
}