mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 07:47:39 +00:00
fix: enable FTS fallback when no embedding provider available (#17725)
When no embedding provider is available (e.g., OAuth mode without API keys), memory_search now falls back to FTS-only mode instead of returning disabled: true. Changes: - embeddings.ts: return null provider with reason instead of throwing - manager.ts: handle null provider, use FTS-only search mode - manager-search.ts: allow searching all models when provider is undefined - memory-tool.ts: expose search mode in results The search results now include a 'mode' field indicating 'hybrid' or 'fts-only'.
This commit is contained in:
@@ -432,3 +432,63 @@ describe("local embedding normalization", () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("FTS-only fallback when no provider available", () => {
|
||||
afterEach(() => {
|
||||
vi.resetAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it("returns null provider with reason when auto mode finds no providers", async () => {
|
||||
vi.mocked(authModule.resolveApiKeyForProvider).mockRejectedValue(
|
||||
new Error('No API key found for provider "openai"'),
|
||||
);
|
||||
|
||||
const result = await createEmbeddingProvider({
|
||||
config: {} as never,
|
||||
provider: "auto",
|
||||
model: "",
|
||||
fallback: "none",
|
||||
});
|
||||
|
||||
expect(result.provider).toBeNull();
|
||||
expect(result.requestedProvider).toBe("auto");
|
||||
expect(result.providerUnavailableReason).toBeDefined();
|
||||
expect(result.providerUnavailableReason).toContain("No API key");
|
||||
});
|
||||
|
||||
it("returns null provider when explicit provider fails with missing API key", async () => {
|
||||
vi.mocked(authModule.resolveApiKeyForProvider).mockRejectedValue(
|
||||
new Error('No API key found for provider "openai"'),
|
||||
);
|
||||
|
||||
const result = await createEmbeddingProvider({
|
||||
config: {} as never,
|
||||
provider: "openai",
|
||||
model: "text-embedding-3-small",
|
||||
fallback: "none",
|
||||
});
|
||||
|
||||
expect(result.provider).toBeNull();
|
||||
expect(result.requestedProvider).toBe("openai");
|
||||
expect(result.providerUnavailableReason).toBeDefined();
|
||||
});
|
||||
|
||||
it("returns null provider when both primary and fallback fail with missing API keys", async () => {
|
||||
vi.mocked(authModule.resolveApiKeyForProvider).mockRejectedValue(
|
||||
new Error("No API key found for provider"),
|
||||
);
|
||||
|
||||
const result = await createEmbeddingProvider({
|
||||
config: {} as never,
|
||||
provider: "openai",
|
||||
model: "text-embedding-3-small",
|
||||
fallback: "gemini",
|
||||
});
|
||||
|
||||
expect(result.provider).toBeNull();
|
||||
expect(result.requestedProvider).toBe("openai");
|
||||
expect(result.fallbackFrom).toBe("openai");
|
||||
expect(result.providerUnavailableReason).toContain("Fallback to gemini failed");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user