Files
openclaw/extensions/tavily/src/tavily-extract-tool.ts
Gustavo Madeira Santana 3da66718f4 Web: derive search provider metadata from plugin contracts (#50935)
Merged via squash.

Prepared head SHA: e1c7d72833
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
2026-03-20 12:41:04 -07:00

75 lines
2.5 KiB
TypeScript

import { Type } from "@sinclair/typebox";
import { jsonResult, readNumberParam, readStringParam } from "openclaw/plugin-sdk/agent-runtime";
import { optionalStringEnum } from "openclaw/plugin-sdk/core";
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime";
import { runTavilyExtract } from "./tavily-client.js";
const TavilyExtractToolSchema = Type.Object(
{
urls: Type.Array(Type.String(), {
description: "One or more URLs to extract content from (max 20).",
minItems: 1,
maxItems: 20,
}),
query: Type.Optional(
Type.String({
description: "Rerank extracted chunks by relevance to this query.",
}),
),
extract_depth: optionalStringEnum(["basic", "advanced"] as const, {
description: '"basic" (default) or "advanced" (for JS-heavy pages).',
}),
chunks_per_source: Type.Optional(
Type.Number({
description: "Chunks per URL (1-5, requires query).",
minimum: 1,
maximum: 5,
}),
),
include_images: Type.Optional(
Type.Boolean({
description: "Include image URLs in extraction results.",
}),
),
},
{ additionalProperties: false },
);
export function createTavilyExtractTool(api: OpenClawPluginApi) {
return {
name: "tavily_extract",
label: "Tavily Extract",
description:
"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)
: [];
if (urls.length === 0) {
throw new Error("tavily_extract requires at least one URL.");
}
const query = readStringParam(rawParams, "query") || undefined;
const extractDepth = readStringParam(rawParams, "extract_depth") || undefined;
const chunksPerSource = readNumberParam(rawParams, "chunks_per_source", {
integer: true,
});
if (chunksPerSource !== undefined && !query) {
throw new Error("tavily_extract requires query when chunks_per_source is set.");
}
const includeImages = rawParams.include_images === true;
return jsonResult(
await runTavilyExtract({
cfg: api.config,
urls,
query,
extractDepth,
chunksPerSource,
includeImages,
}),
);
},
};
}