mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(tavily): reject blank extract URLs (#111333)
* fix(tavily): reject blank extract URLs Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> * fix(tavily): normalize tool string arrays Co-authored-by: VectorPeak <73048950+VectorPeak@users.noreply.github.com> --------- Co-authored-by: chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com> Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
co-authored by
chatgpt-codex-connector[bot] <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
Peter Steinberger
parent
359859d343
commit
fe9e018045
@@ -3,6 +3,7 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import {
|
||||
jsonResult,
|
||||
readPositiveIntegerParam,
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "openclaw/plugin-sdk/provider-web-search";
|
||||
import { Type } from "typebox";
|
||||
@@ -49,9 +50,7 @@ export function createTavilyExtractTool(api: OpenClawPluginApi, ctx?: TavilyTool
|
||||
"Extract clean content from one or more URLs using Tavily. Handles JS-rendered pages. Supports query-focused chunking.",
|
||||
parameters: TavilyExtractToolSchema,
|
||||
execute: async (_toolCallId: string, rawParams: Record<string, unknown>) => {
|
||||
const urls = Array.isArray(rawParams.urls)
|
||||
? (rawParams.urls as string[]).filter(Boolean)
|
||||
: [];
|
||||
const urls = readStringArrayParam(rawParams, "urls") ?? [];
|
||||
if (urls.length === 0) {
|
||||
throw new Error("tavily_extract requires at least one URL.");
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
|
||||
import {
|
||||
jsonResult,
|
||||
readPositiveIntegerParam,
|
||||
readStringArrayParam,
|
||||
readStringParam,
|
||||
} from "openclaw/plugin-sdk/provider-web-search";
|
||||
import { Type } from "typebox";
|
||||
@@ -65,12 +66,8 @@ export function createTavilySearchTool(api: OpenClawPluginApi, ctx?: TavilyToolC
|
||||
});
|
||||
const includeAnswer = rawParams.include_answer === true;
|
||||
const timeRange = readStringParam(rawParams, "time_range") || undefined;
|
||||
const includeDomains = Array.isArray(rawParams.include_domains)
|
||||
? (rawParams.include_domains as string[]).filter(Boolean)
|
||||
: undefined;
|
||||
const excludeDomains = Array.isArray(rawParams.exclude_domains)
|
||||
? (rawParams.exclude_domains as string[]).filter(Boolean)
|
||||
: undefined;
|
||||
const includeDomains = readStringArrayParam(rawParams, "include_domains");
|
||||
const excludeDomains = readStringArrayParam(rawParams, "exclude_domains");
|
||||
|
||||
return jsonResult(
|
||||
await runTavilySearch({
|
||||
@@ -81,8 +78,8 @@ export function createTavilySearchTool(api: OpenClawPluginApi, ctx?: TavilyToolC
|
||||
maxResults,
|
||||
includeAnswer,
|
||||
timeRange,
|
||||
includeDomains: includeDomains?.length ? includeDomains : undefined,
|
||||
excludeDomains: excludeDomains?.length ? excludeDomains : undefined,
|
||||
includeDomains,
|
||||
excludeDomains,
|
||||
}),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -179,8 +179,8 @@ describe("tavily tools", () => {
|
||||
max_results: 5,
|
||||
include_answer: true,
|
||||
time_range: "week",
|
||||
include_domains: ["docs.openclaw.ai", "", "openclaw.ai"],
|
||||
exclude_domains: ["bad.example", ""],
|
||||
include_domains: [" docs.openclaw.ai ", " ", "openclaw.ai"],
|
||||
exclude_domains: [" bad.example ", ""],
|
||||
});
|
||||
|
||||
expect(runTavilySearch).toHaveBeenCalledWith({
|
||||
@@ -313,7 +313,7 @@ describe("tavily tools", () => {
|
||||
await expect(
|
||||
searchTool.execute("call-2", {
|
||||
query: "simple",
|
||||
include_domains: [""],
|
||||
include_domains: [" "],
|
||||
exclude_domains: [],
|
||||
}),
|
||||
).resolves.toEqual({
|
||||
@@ -351,6 +351,28 @@ describe("tavily tools", () => {
|
||||
expect(runTavilyExtract).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects blank extract URLs before Tavily calls and trims valid URLs", async () => {
|
||||
const tool = createTavilyExtractTool(fakeApi());
|
||||
|
||||
await expect(
|
||||
tool.execute("extract-call", {
|
||||
urls: [" "],
|
||||
}),
|
||||
).rejects.toThrow("tavily_extract requires at least one URL.");
|
||||
|
||||
expect(runTavilyExtract).not.toHaveBeenCalled();
|
||||
|
||||
await tool.execute("extract-call", {
|
||||
urls: [" https://example.com/article "],
|
||||
});
|
||||
|
||||
const extractParams = requireFirstMockArg(
|
||||
runTavilyExtract,
|
||||
"Tavily extract params",
|
||||
) as TavilyExtractParams;
|
||||
expect(extractParams.urls).toEqual(["https://example.com/article"]);
|
||||
});
|
||||
|
||||
it("rejects fractional and out-of-range integer options before Tavily calls", async () => {
|
||||
const searchTool = createTavilySearchTool(fakeApi());
|
||||
await expect(
|
||||
|
||||
Reference in New Issue
Block a user