diff --git a/extensions/tavily/src/tavily-extract-tool.ts b/extensions/tavily/src/tavily-extract-tool.ts index c910a6825c0..c50f8696573 100644 --- a/extensions/tavily/src/tavily-extract-tool.ts +++ b/extensions/tavily/src/tavily-extract-tool.ts @@ -1,5 +1,3 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; -import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/plugin-entry"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime"; import { jsonResult, @@ -8,20 +6,9 @@ import { } from "openclaw/plugin-sdk/provider-web-search"; import { Type } from "typebox"; import { runTavilyExtract } from "./tavily-client.js"; +import { resolveTavilyToolConfig, type TavilyToolConfigContext } from "./tavily-tool-config.js"; import { optionalStringEnum } from "./tavily-tool-schema.js"; -type TavilyToolConfigContext = Pick< - OpenClawPluginToolContext, - "config" | "runtimeConfig" | "getRuntimeConfig" ->; - -function resolveTavilyToolConfig( - api: OpenClawPluginApi, - ctx?: TavilyToolConfigContext, -): OpenClawConfig { - return ctx?.getRuntimeConfig?.() ?? ctx?.runtimeConfig ?? ctx?.config ?? api.config; -} - const TavilyExtractToolSchema = Type.Object( { urls: Type.Array(Type.String(), { diff --git a/extensions/tavily/src/tavily-search-provider.ts b/extensions/tavily/src/tavily-search-provider.ts index 4063ffa2e03..66baf543669 100644 --- a/extensions/tavily/src/tavily-search-provider.ts +++ b/extensions/tavily/src/tavily-search-provider.ts @@ -1,10 +1,6 @@ import { readPositiveIntegerParam } from "openclaw/plugin-sdk/param-readers"; -import { - createWebSearchProviderContractFields, - type WebSearchProviderPlugin, -} from "openclaw/plugin-sdk/provider-web-search-contract"; - -const TAVILY_CREDENTIAL_PATH = "plugins.entries.tavily.config.webSearch.apiKey"; +import { type WebSearchProviderPlugin } from "openclaw/plugin-sdk/provider-web-search-contract"; +import { buildTavilyWebSearchProviderBase } from "../web-search-shared.js"; type TavilyClientModule = typeof import("./tavily-client.js"); @@ -31,23 +27,7 @@ const GenericTavilySearchSchema = { export function createTavilyWebSearchProvider(): WebSearchProviderPlugin { return { - id: "tavily", - label: "Tavily Search", - hint: "Structured results with domain filters and AI answer summaries", - onboardingScopes: ["text-inference"], - credentialLabel: "Tavily API key", - envVars: ["TAVILY_API_KEY"], - placeholder: "tvly-...", - signupUrl: "https://tavily.com/", - docsUrl: "https://docs.openclaw.ai/tools/tavily", - autoDetectOrder: 70, - credentialPath: TAVILY_CREDENTIAL_PATH, - ...createWebSearchProviderContractFields({ - credentialPath: TAVILY_CREDENTIAL_PATH, - searchCredential: { type: "scoped", scopeId: "tavily" }, - configuredCredential: { pluginId: "tavily" }, - selectionPluginId: "tavily", - }), + ...buildTavilyWebSearchProviderBase(), createTool: (ctx) => ({ description: "Search the web using Tavily. Returns structured results with snippets. Use tavily_search for Tavily-specific options like search depth, topic filtering, or AI answers.", diff --git a/extensions/tavily/src/tavily-search-tool.ts b/extensions/tavily/src/tavily-search-tool.ts index cc45b893ef1..f81cb7de14b 100644 --- a/extensions/tavily/src/tavily-search-tool.ts +++ b/extensions/tavily/src/tavily-search-tool.ts @@ -1,5 +1,3 @@ -import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; -import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/plugin-entry"; import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime"; import { jsonResult, @@ -8,20 +6,9 @@ import { } from "openclaw/plugin-sdk/provider-web-search"; import { Type } from "typebox"; import { runTavilySearch } from "./tavily-client.js"; +import { resolveTavilyToolConfig, type TavilyToolConfigContext } from "./tavily-tool-config.js"; import { optionalStringEnum } from "./tavily-tool-schema.js"; -type TavilyToolConfigContext = Pick< - OpenClawPluginToolContext, - "config" | "runtimeConfig" | "getRuntimeConfig" ->; - -function resolveTavilyToolConfig( - api: OpenClawPluginApi, - ctx?: TavilyToolConfigContext, -): OpenClawConfig { - return ctx?.getRuntimeConfig?.() ?? ctx?.runtimeConfig ?? ctx?.config ?? api.config; -} - const TavilySearchToolSchema = Type.Object( { query: Type.String({ description: "Search query string." }), diff --git a/extensions/tavily/src/tavily-tool-config.ts b/extensions/tavily/src/tavily-tool-config.ts new file mode 100644 index 00000000000..fcd74baa43d --- /dev/null +++ b/extensions/tavily/src/tavily-tool-config.ts @@ -0,0 +1,15 @@ +import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts"; +import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/plugin-entry"; +import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-runtime"; + +export type TavilyToolConfigContext = Pick< + OpenClawPluginToolContext, + "config" | "runtimeConfig" | "getRuntimeConfig" +>; + +export function resolveTavilyToolConfig( + api: OpenClawPluginApi, + ctx?: TavilyToolConfigContext, +): OpenClawConfig { + return ctx?.getRuntimeConfig?.() ?? ctx?.runtimeConfig ?? ctx?.config ?? api.config; +} diff --git a/extensions/tavily/web-search-contract-api.ts b/extensions/tavily/web-search-contract-api.ts index b8b8e31c189..ec3361313f5 100644 --- a/extensions/tavily/web-search-contract-api.ts +++ b/extensions/tavily/web-search-contract-api.ts @@ -1,29 +1,9 @@ -import { - createWebSearchProviderContractFields, - type WebSearchProviderPlugin, -} from "openclaw/plugin-sdk/provider-web-search-contract"; +import { type WebSearchProviderPlugin } from "openclaw/plugin-sdk/provider-web-search-contract"; +import { buildTavilyWebSearchProviderBase } from "./web-search-shared.js"; export function createTavilyWebSearchProvider(): WebSearchProviderPlugin { - const credentialPath = "plugins.entries.tavily.config.webSearch.apiKey"; - return { - id: "tavily", - label: "Tavily Search", - hint: "Structured results with domain filters and AI answer summaries", - onboardingScopes: ["text-inference"], - credentialLabel: "Tavily API key", - envVars: ["TAVILY_API_KEY"], - placeholder: "tvly-...", - signupUrl: "https://tavily.com/", - docsUrl: "https://docs.openclaw.ai/tools/tavily", - autoDetectOrder: 70, - credentialPath, - ...createWebSearchProviderContractFields({ - credentialPath, - searchCredential: { type: "scoped", scopeId: "tavily" }, - configuredCredential: { pluginId: "tavily" }, - selectionPluginId: "tavily", - }), + ...buildTavilyWebSearchProviderBase(), createTool: () => null, }; } diff --git a/extensions/tavily/web-search-shared.ts b/extensions/tavily/web-search-shared.ts new file mode 100644 index 00000000000..1898f95a47f --- /dev/null +++ b/extensions/tavily/web-search-shared.ts @@ -0,0 +1,28 @@ +import { + createWebSearchProviderContractFields, + type WebSearchProviderPlugin, +} from "openclaw/plugin-sdk/provider-web-search-contract"; + +export const TAVILY_CREDENTIAL_PATH = "plugins.entries.tavily.config.webSearch.apiKey"; + +export function buildTavilyWebSearchProviderBase(): Omit { + return { + id: "tavily", + label: "Tavily Search", + hint: "Structured results with domain filters and AI answer summaries", + onboardingScopes: ["text-inference"], + credentialLabel: "Tavily API key", + envVars: ["TAVILY_API_KEY"], + placeholder: "tvly-...", + signupUrl: "https://tavily.com/", + docsUrl: "https://docs.openclaw.ai/tools/tavily", + autoDetectOrder: 70, + credentialPath: TAVILY_CREDENTIAL_PATH, + ...createWebSearchProviderContractFields({ + credentialPath: TAVILY_CREDENTIAL_PATH, + searchCredential: { type: "scoped", scopeId: "tavily" }, + configuredCredential: { pluginId: "tavily" }, + selectionPluginId: "tavily", + }), + }; +}