Files
openclaw/src/plugins/memory-embedding-providers.ts
glitch 3cec3bd48b fix(memory): share embedding providers across plugin runtime splits (#55945)
Merged via squash.

Prepared head SHA: e913806211
Co-authored-by: glitch418x <189487110+glitch418x@users.noreply.github.com>
Co-authored-by: altaywtf <9790196+altaywtf@users.noreply.github.com>
Reviewed-by: @altaywtf
2026-03-27 21:40:19 +03:00

139 lines
4.2 KiB
TypeScript

import type { EmbeddingInput } from "../../packages/memory-host-sdk/src/host/embedding-inputs.js";
import type { OpenClawConfig } from "../config/config.js";
import type { SecretInput } from "../config/types.secrets.js";
export type MemoryEmbeddingBatchChunk = {
text: string;
embeddingInput?: EmbeddingInput;
};
export type MemoryEmbeddingBatchOptions = {
agentId: string;
chunks: MemoryEmbeddingBatchChunk[];
wait: boolean;
concurrency: number;
pollIntervalMs: number;
timeoutMs: number;
debug: (message: string, data?: Record<string, unknown>) => void;
};
export type MemoryEmbeddingProviderRuntime = {
id: string;
cacheKeyData?: Record<string, unknown>;
batchEmbed?: (options: MemoryEmbeddingBatchOptions) => Promise<number[][] | null>;
};
export type MemoryEmbeddingProvider = {
id: string;
model: string;
maxInputTokens?: number;
embedQuery: (text: string) => Promise<number[]>;
embedBatch: (texts: string[]) => Promise<number[][]>;
embedBatchInputs?: (inputs: EmbeddingInput[]) => Promise<number[][]>;
};
export type MemoryEmbeddingProviderCreateOptions = {
config: OpenClawConfig;
agentDir?: string;
remote?: {
baseUrl?: string;
apiKey?: SecretInput;
headers?: Record<string, string>;
};
model: string;
local?: {
modelPath?: string;
modelCacheDir?: string;
};
outputDimensionality?: number;
};
export type MemoryEmbeddingProviderCreateResult = {
provider: MemoryEmbeddingProvider | null;
runtime?: MemoryEmbeddingProviderRuntime;
};
export type MemoryEmbeddingProviderAdapter = {
id: string;
defaultModel?: string;
transport?: "local" | "remote";
autoSelectPriority?: number;
allowExplicitWhenConfiguredAuto?: boolean;
supportsMultimodalEmbeddings?: (params: { model: string }) => boolean;
create: (
options: MemoryEmbeddingProviderCreateOptions,
) => Promise<MemoryEmbeddingProviderCreateResult>;
formatSetupError?: (err: unknown) => string;
shouldContinueAutoSelection?: (err: unknown) => boolean;
};
export type RegisteredMemoryEmbeddingProvider = {
adapter: MemoryEmbeddingProviderAdapter;
ownerPluginId?: string;
};
const MEMORY_EMBEDDING_PROVIDERS_KEY = Symbol.for("openclaw.memoryEmbeddingProviders");
function getMemoryEmbeddingProviders(): Map<string, RegisteredMemoryEmbeddingProvider> {
const globalStore = globalThis as Record<PropertyKey, unknown>;
const existing = globalStore[MEMORY_EMBEDDING_PROVIDERS_KEY];
if (existing instanceof Map) {
return existing as Map<string, RegisteredMemoryEmbeddingProvider>;
}
const created = new Map<string, RegisteredMemoryEmbeddingProvider>();
globalStore[MEMORY_EMBEDDING_PROVIDERS_KEY] = created;
return created;
}
export function registerMemoryEmbeddingProvider(
adapter: MemoryEmbeddingProviderAdapter,
options?: { ownerPluginId?: string },
): void {
getMemoryEmbeddingProviders().set(adapter.id, {
adapter,
ownerPluginId: options?.ownerPluginId,
});
}
export function getRegisteredMemoryEmbeddingProvider(
id: string,
): RegisteredMemoryEmbeddingProvider | undefined {
return getMemoryEmbeddingProviders().get(id);
}
export function getMemoryEmbeddingProvider(id: string): MemoryEmbeddingProviderAdapter | undefined {
return getMemoryEmbeddingProviders().get(id)?.adapter;
}
export function listRegisteredMemoryEmbeddingProviders(): RegisteredMemoryEmbeddingProvider[] {
return Array.from(getMemoryEmbeddingProviders().values());
}
export function listMemoryEmbeddingProviders(): MemoryEmbeddingProviderAdapter[] {
return listRegisteredMemoryEmbeddingProviders().map((entry) => entry.adapter);
}
export function restoreMemoryEmbeddingProviders(adapters: MemoryEmbeddingProviderAdapter[]): void {
getMemoryEmbeddingProviders().clear();
for (const adapter of adapters) {
registerMemoryEmbeddingProvider(adapter);
}
}
export function restoreRegisteredMemoryEmbeddingProviders(
entries: RegisteredMemoryEmbeddingProvider[],
): void {
getMemoryEmbeddingProviders().clear();
for (const entry of entries) {
registerMemoryEmbeddingProvider(entry.adapter, {
ownerPluginId: entry.ownerPluginId,
});
}
}
export function clearMemoryEmbeddingProviders(): void {
getMemoryEmbeddingProviders().clear();
}
export const _resetMemoryEmbeddingProviders = clearMemoryEmbeddingProviders;