@@ -7,6 +7,7 @@ import { convert } from "html-to-text";
77import { Athena , Dict } from "../../core/athena.js" ;
88import { JinaSearch } from "./jina.js" ;
99import { ExaSearch } from "./exa.js" ;
10+ import { TavilySearch } from "./tavily.js" ;
1011import { PluginBase } from "../plugin-base.js" ;
1112
1213export default class Http extends PluginBase {
@@ -22,6 +23,7 @@ export default class Http extends PluginBase {
2223
2324 jina ! : JinaSearch ;
2425 exa ! : ExaSearch ;
26+ tavily ! : TavilySearch ;
2527 boundAthenaPrivateEventHandler ! : ( name : string , args : Dict < any > ) => void ;
2628
2729 async load ( athena : Athena ) {
@@ -37,6 +39,12 @@ export default class Http extends PluginBase {
3739 apiKey : this . config . exa . api_key ,
3840 } ) ;
3941 }
42+ if ( this . config . tavily ) {
43+ this . tavily = new TavilySearch ( {
44+ baseUrl : this . config . tavily . base_url ,
45+ apiKey : this . config . tavily . api_key ,
46+ } ) ;
47+ }
4048 this . boundAthenaPrivateEventHandler =
4149 this . athenaPrivateEventHandler . bind ( this ) ;
4250 athena . on ( "private-event" , this . boundAthenaPrivateEventHandler ) ;
@@ -214,6 +222,63 @@ export default class Http extends PluginBase {
214222 } ,
215223 ) ;
216224 }
225+ if ( this . config . tavily ) {
226+ athena . registerTool (
227+ {
228+ name : "http/tavily-search" ,
229+ desc : "Searches the web for information using Tavily API." ,
230+ args : {
231+ query : {
232+ type : "string" ,
233+ desc : "The query to search for." ,
234+ required : true ,
235+ } ,
236+ } ,
237+ retvals : {
238+ results : {
239+ type : "array" ,
240+ desc : "The results of the search." ,
241+ required : true ,
242+ of : {
243+ type : "object" ,
244+ desc : "A single search result." ,
245+ of : {
246+ title : {
247+ type : "string" ,
248+ desc : "The title of the result." ,
249+ required : true ,
250+ } ,
251+ url : {
252+ type : "string" ,
253+ desc : "The URL of the result." ,
254+ required : true ,
255+ } ,
256+ content : {
257+ type : "string" ,
258+ desc : "Text content snippet." ,
259+ required : true ,
260+ } ,
261+ } ,
262+ required : true ,
263+ } ,
264+ } ,
265+ } ,
266+ } ,
267+ {
268+ fn : async ( args : Dict < any > ) => {
269+ const results = await this . tavily . search ( args . query ) ;
270+ return { results } ;
271+ } ,
272+ explain_args : ( args : Dict < any > ) => ( {
273+ summary : `Searching the web with Tavily for ${ args . query } ...` ,
274+ } ) ,
275+ explain_retvals : ( args : Dict < any > , retvals : Dict < any > ) => ( {
276+ summary : `Found ${ retvals . results . length } results with Tavily for ${ args . query } .` ,
277+ details : JSON . stringify ( retvals . results ) ,
278+ } ) ,
279+ } ,
280+ ) ;
281+ }
217282 athena . registerTool (
218283 {
219284 name : "http/download-file" ,
@@ -289,6 +354,9 @@ export default class Http extends PluginBase {
289354 if ( this . config . exa ) {
290355 athena . deregisterTool ( "http/exa-search" ) ;
291356 }
357+ if ( this . config . tavily ) {
358+ athena . deregisterTool ( "http/tavily-search" ) ;
359+ }
292360 athena . deregisterTool ( "http/download-file" ) ;
293361 }
294362
@@ -306,6 +374,12 @@ export default class Http extends PluginBase {
306374 apiKey : this . config . exa . api_key || args . token ,
307375 } ) ;
308376 }
377+ if ( this . config . tavily ) {
378+ this . tavily = new TavilySearch ( {
379+ baseUrl : this . config . tavily . base_url ,
380+ apiKey : args . token ,
381+ } ) ;
382+ }
309383 }
310384 }
311385}
0 commit comments