mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-31 14:08:38 +00:00
fix(brave): bound search error bodies
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import { readProviderJsonResponse } from "openclaw/plugin-sdk/provider-http";
|
||||
import {
|
||||
assertOkOrThrowProviderError,
|
||||
readProviderJsonResponse,
|
||||
} from "openclaw/plugin-sdk/provider-http";
|
||||
import type { SearchConfigRecord } from "openclaw/plugin-sdk/provider-web-search";
|
||||
import {
|
||||
buildSearchCacheKey,
|
||||
@@ -225,12 +228,7 @@ async function runBraveLlmContextSearch(params: {
|
||||
ok: response.ok,
|
||||
durationMs: Date.now() - startedAt,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const detail = await response.text();
|
||||
throw new Error(
|
||||
`Brave LLM Context API error (${response.status}): ${detail || response.statusText}`,
|
||||
);
|
||||
}
|
||||
await assertOkOrThrowProviderError(response, "Brave LLM Context API error");
|
||||
|
||||
const data = await readProviderJsonResponse<BraveLlmContextResponse>(
|
||||
response,
|
||||
@@ -312,12 +310,7 @@ async function runBraveWebSearch(params: {
|
||||
ok: response.ok,
|
||||
durationMs: Date.now() - startedAt,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const detail = await response.text();
|
||||
throw new Error(
|
||||
`Brave Search API error (${response.status}): ${detail || response.statusText}`,
|
||||
);
|
||||
}
|
||||
await assertOkOrThrowProviderError(response, "Brave Search API error");
|
||||
|
||||
const data = await readProviderJsonResponse<BraveSearchResponse>(
|
||||
response,
|
||||
|
||||
@@ -88,6 +88,23 @@ function fetchRequestInit(mockFetch: { mock: { calls: Array<Array<unknown>> } },
|
||||
return fetchCall(mockFetch, index)[1];
|
||||
}
|
||||
|
||||
function createBodyOnlyErrorResponse(params: { body: string; status: number }): Response {
|
||||
const bytes = new TextEncoder().encode(params.body);
|
||||
const body = new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
controller.enqueue(bytes);
|
||||
controller.close();
|
||||
},
|
||||
});
|
||||
return {
|
||||
ok: false,
|
||||
status: params.status,
|
||||
statusText: "Too Many Requests",
|
||||
headers: new Headers(),
|
||||
body,
|
||||
} as Response;
|
||||
}
|
||||
|
||||
describe("brave web search provider", () => {
|
||||
const priorFetch = global.fetch;
|
||||
|
||||
@@ -347,6 +364,66 @@ describe("brave web search provider", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("bounds Brave web error bodies without using response.text", async () => {
|
||||
vi.stubEnv("BRAVE_API_KEY", "");
|
||||
const mockFetch = vi.fn(async (_input?: unknown, _init?: unknown) =>
|
||||
createBodyOnlyErrorResponse({
|
||||
status: 429,
|
||||
body: `${"x".repeat(24 * 1024)}tail-marker`,
|
||||
}),
|
||||
);
|
||||
global.fetch = mockFetch as typeof global.fetch;
|
||||
|
||||
const provider = createBraveWebSearchProvider();
|
||||
const tool = provider.createTool({
|
||||
config: {},
|
||||
searchConfig: {
|
||||
apiKey: "brave-test-key",
|
||||
brave: { mode: "web" },
|
||||
},
|
||||
});
|
||||
if (!tool) {
|
||||
throw new Error("Expected tool definition");
|
||||
}
|
||||
|
||||
const error = await tool.execute({ query: "latest ai news" }).catch((value: unknown) => value);
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
expect(message).toContain("Brave Search API error (429):");
|
||||
expect(message).not.toContain("tail-marker");
|
||||
expect(message.length).toBeLessThan(700);
|
||||
});
|
||||
|
||||
it("bounds Brave llm-context error bodies without using response.text", async () => {
|
||||
vi.stubEnv("BRAVE_API_KEY", "");
|
||||
const mockFetch = vi.fn(async (_input?: unknown, _init?: unknown) =>
|
||||
createBodyOnlyErrorResponse({
|
||||
status: 429,
|
||||
body: `${"x".repeat(24 * 1024)}tail-marker`,
|
||||
}),
|
||||
);
|
||||
global.fetch = mockFetch as typeof global.fetch;
|
||||
|
||||
const provider = createBraveWebSearchProvider();
|
||||
const tool = provider.createTool({
|
||||
config: {},
|
||||
searchConfig: {
|
||||
apiKey: "brave-test-key",
|
||||
brave: { mode: "llm-context" },
|
||||
},
|
||||
});
|
||||
if (!tool) {
|
||||
throw new Error("Expected tool definition");
|
||||
}
|
||||
|
||||
const error = await tool.execute({ query: "latest ai news" }).catch((value: unknown) => value);
|
||||
expect(error).toBeInstanceOf(Error);
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
expect(message).toContain("Brave LLM Context API error (429):");
|
||||
expect(message).not.toContain("tail-marker");
|
||||
expect(message.length).toBeLessThan(700);
|
||||
});
|
||||
|
||||
it("keeps Brave cache entries isolated by baseUrl", async () => {
|
||||
vi.stubEnv("BRAVE_API_KEY", "");
|
||||
const mockFetch = vi.fn(async (_input?: unknown, _init?: unknown) => {
|
||||
|
||||
Reference in New Issue
Block a user