import { createRemoteEmbeddingProvider, resolveRemoteEmbeddingClient, type MemoryEmbeddingProvider, type MemoryEmbeddingProviderCreateOptions, } from "openclaw/plugin-sdk/memory-core-host-engine-embeddings"; import type { SsrFPolicy } from "openclaw/plugin-sdk/ssrf-runtime"; import { OPENAI_DEFAULT_EMBEDDING_MODEL } from "./default-models.js"; export type OpenAiEmbeddingClient = { baseUrl: string; headers: Record; ssrfPolicy?: SsrFPolicy; fetchImpl?: typeof fetch; model: string; }; const DEFAULT_OPENAI_BASE_URL = "https://api.openai.com/v1"; export const DEFAULT_OPENAI_EMBEDDING_MODEL = OPENAI_DEFAULT_EMBEDDING_MODEL; const OPENAI_MAX_INPUT_TOKENS: Record = { "text-embedding-3-small": 8192, "text-embedding-3-large": 8192, "text-embedding-ada-002": 8191, }; export function normalizeOpenAiModel(model: string): string { const trimmed = model.trim(); if (!trimmed) { return DEFAULT_OPENAI_EMBEDDING_MODEL; } return trimmed.startsWith("openai/") ? trimmed.slice("openai/".length) : trimmed; } export async function createOpenAiEmbeddingProvider( options: MemoryEmbeddingProviderCreateOptions, ): Promise<{ provider: MemoryEmbeddingProvider; client: OpenAiEmbeddingClient }> { const client = await resolveOpenAiEmbeddingClient(options); return { provider: createRemoteEmbeddingProvider({ id: "openai", client, errorPrefix: "openai embeddings failed", maxInputTokens: OPENAI_MAX_INPUT_TOKENS[client.model], }), client, }; } export async function resolveOpenAiEmbeddingClient( options: MemoryEmbeddingProviderCreateOptions, ): Promise { return await resolveRemoteEmbeddingClient({ provider: "openai", options, defaultBaseUrl: DEFAULT_OPENAI_BASE_URL, normalizeModel: normalizeOpenAiModel, }); }