11// Tavily helper module supports config behavior.
22import type { OpenClawConfig } from "openclaw/plugin-sdk/config-contracts" ;
3+ import { canResolveEnvSecretRefInReadOnlyPath } from "openclaw/plugin-sdk/extension-shared" ;
34import { resolvePositiveTimeoutSeconds } from "openclaw/plugin-sdk/provider-web-search" ;
4- import {
5- normalizeResolvedSecretInputString ,
6- normalizeSecretInput ,
7- } from "openclaw/plugin-sdk/secret-input" ;
5+ import { resolveSecretInputString , normalizeSecretInput } from "openclaw/plugin-sdk/secret-input" ;
86import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime" ;
97
108export const DEFAULT_TAVILY_BASE_URL = "https://api.tavily.com" ;
119export const DEFAULT_TAVILY_SEARCH_TIMEOUT_SECONDS = 30 ;
1210export const DEFAULT_TAVILY_EXTRACT_TIMEOUT_SECONDS = 60 ;
11+ const TAVILY_API_KEY_ENV_VAR = "TAVILY_API_KEY" ;
1312
1413type TavilySearchConfig =
1514 | {
@@ -34,22 +33,63 @@ export function resolveTavilySearchConfig(cfg?: OpenClawConfig): TavilySearchCon
3433 return undefined ;
3534}
3635
37- function normalizeConfiguredSecret ( value : unknown , path : string ) : string | undefined {
38- return normalizeSecretInput (
39- normalizeResolvedSecretInputString ( {
40- value,
41- path,
42- } ) ,
43- ) ;
36+ type ConfiguredSecretResolution =
37+ | { status : "available" ; value : string }
38+ | { status : "missing" }
39+ | { status : "blocked" } ;
40+
41+ function resolveConfiguredSecret (
42+ value : unknown ,
43+ path : string ,
44+ cfg ?: OpenClawConfig ,
45+ ) : ConfiguredSecretResolution {
46+ const resolved = resolveSecretInputString ( {
47+ value,
48+ path,
49+ defaults : cfg ?. secrets ?. defaults ,
50+ mode : "inspect" ,
51+ } ) ;
52+ if ( resolved . status === "available" ) {
53+ const normalized = normalizeSecretInput ( resolved . value ) ;
54+ return normalized ? { status : "available" , value : normalized } : { status : "missing" } ;
55+ }
56+ if ( resolved . status === "missing" ) {
57+ return { status : "missing" } ;
58+ }
59+ if ( resolved . ref . source !== "env" ) {
60+ return { status : "blocked" } ;
61+ }
62+ const envVarName = resolved . ref . id . trim ( ) ;
63+ if ( envVarName !== TAVILY_API_KEY_ENV_VAR ) {
64+ return { status : "blocked" } ;
65+ }
66+ if (
67+ ! canResolveEnvSecretRefInReadOnlyPath ( {
68+ cfg,
69+ provider : resolved . ref . provider ,
70+ id : envVarName ,
71+ } )
72+ ) {
73+ return { status : "blocked" } ;
74+ }
75+ const envValue = normalizeSecretInput ( process . env [ envVarName ] ) ;
76+ return envValue ? { status : "available" , value : envValue } : { status : "missing" } ;
4477}
4578
4679export function resolveTavilyApiKey ( cfg ?: OpenClawConfig ) : string | undefined {
4780 const search = resolveTavilySearchConfig ( cfg ) ;
48- return (
49- normalizeConfiguredSecret ( search ?. apiKey , "plugins.entries.tavily.config.webSearch.apiKey" ) ||
50- normalizeSecretInput ( process . env . TAVILY_API_KEY ) ||
51- undefined
81+ const resolved = resolveConfiguredSecret (
82+ search ?. apiKey ,
83+ "plugins.entries.tavily.config.webSearch.apiKey" ,
84+ cfg ,
5285 ) ;
86+ if ( resolved . status === "available" ) {
87+ return resolved . value ;
88+ }
89+ if ( resolved . status === "blocked" ) {
90+ return undefined ;
91+ }
92+ return normalizeSecretInput ( process . env . TAVILY_API_KEY ) || undefined ;
5393}
5494
5595export function resolveTavilyBaseUrl ( cfg ?: OpenClawConfig ) : string {
0 commit comments