@elizaos/plugin-web-search 0.1.9 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,10 +40,10 @@ export default {
40
40
  ```
41
41
 
42
42
  **Custom Usage**
43
- If you want custom usage, for example, twitter-client to search the web before posting a tweet, you can also import the webSearchService and use it directly. Here's how you can do it:
43
+ If you want custom usage, for example, a social media client to search the web before posting, you can also import the webSearchService and use it directly. Here's how you can do it:
44
44
 
45
45
  ```typescript
46
- // packages/client-twitter/src/post.ts
46
+ // Example usage in a social media client
47
47
  const webSearchService = new WebSearchService();
48
48
  await webSearchService.initialize(runtime);
49
49
  const latestNews = await webSearchService.search(
@@ -58,7 +58,7 @@ const state = await this.runtime.composeState(
58
58
  }
59
59
  );
60
60
 
61
- // Then modify the tweet template to include the {{latestNews}} and however you need
61
+ // Then modify the post template to include the {{latestNews}} and however you need
62
62
  ```
63
63
 
64
64
  ## Features
package/dist/index.d.ts CHANGED
@@ -1,5 +1,67 @@
1
- import { Plugin } from '@elizaos/core';
1
+ import * as _elizaos_core from '@elizaos/core';
2
+ import { Service, IAgentRuntime } from '@elizaos/core';
2
3
 
3
- declare const webSearchPlugin: Plugin;
4
+ interface ITavilyService extends Service {
5
+ search(query: string, options?: SearchOptions): Promise<SearchResponse>;
6
+ }
7
+ type SearchResult = {
8
+ title: string;
9
+ url: string;
10
+ content: string;
11
+ rawContent?: string;
12
+ score: number;
13
+ publishedDate?: string;
14
+ };
15
+ type SearchImage = {
16
+ url: string;
17
+ description?: string;
18
+ };
19
+ type SearchResponse = {
20
+ answer?: string;
21
+ query: string;
22
+ responseTime: number;
23
+ images: SearchImage[];
24
+ results: SearchResult[];
25
+ };
26
+ interface SearchOptions {
27
+ auto_parameters?: boolean;
28
+ topic?: "general" | "news" | "finance";
29
+ search_depth?: "basic" | "advanced";
30
+ chunks_per_source?: number;
31
+ max_results?: number;
32
+ time_range?: "day" | "week" | "month" | "year" | "d" | "w" | "m" | "y";
33
+ start_date?: string;
34
+ end_date?: string;
35
+ include_answer?: boolean | "basic" | "advanced";
36
+ include_raw_content?: boolean | "markdown" | "text";
37
+ include_images?: boolean;
38
+ include_image_descriptions?: boolean;
39
+ include_favicon?: boolean;
40
+ include_domains?: string[];
41
+ exclude_domains?: string[];
42
+ country?: string;
43
+ }
44
+
45
+ declare class TavilyService extends Service implements ITavilyService {
46
+ static serviceType: "TAVILY";
47
+ private tavilyClient;
48
+ constructor(runtime: IAgentRuntime);
49
+ static start(runtime: IAgentRuntime): Promise<TavilyService>;
50
+ initialize(runtime: IAgentRuntime): Promise<void>;
51
+ get capabilityDescription(): string;
52
+ stop(): Promise<void>;
53
+ search(query: string, options?: SearchOptions): Promise<SearchResponse>;
54
+ }
55
+
56
+ declare const webSearchPlugin: {
57
+ name: string;
58
+ description: string;
59
+ actions: _elizaos_core.Action[];
60
+ evaluators: any[];
61
+ providers: any[];
62
+ services: (typeof TavilyService)[];
63
+ clients: any[];
64
+ adapters: any[];
65
+ };
4
66
 
5
67
  export { webSearchPlugin as default, webSearchPlugin };
package/dist/index.js CHANGED
@@ -1,60 +1,105 @@
1
1
  // src/actions/webSearch.ts
2
2
  import {
3
- elizaLogger
3
+ logger,
4
+ ModelType,
5
+ composePromptFromState,
6
+ parseKeyValueXml
4
7
  } from "@elizaos/core";
5
- import { encodingForModel } from "js-tiktoken";
8
+ var DEFAULT_MAX_WEB_SEARCH_CHARS = 16e3;
9
+ function buildExtractionTemplate(conversationContext) {
10
+ return `# Web Search Parameter Extraction
6
11
 
7
- // src/services/webSearchService.ts
8
- import {
9
- Service,
10
- ServiceType
11
- } from "@elizaos/core";
12
- import { tavily } from "@tavily/core";
13
- var WebSearchService = class _WebSearchService extends Service {
14
- tavilyClient;
15
- async initialize(_runtime) {
16
- const apiKey = _runtime.getSetting("TAVILY_API_KEY");
17
- if (!apiKey) {
18
- throw new Error("TAVILY_API_KEY is not set");
19
- }
20
- this.tavilyClient = tavily({ apiKey });
21
- }
22
- getInstance() {
23
- return _WebSearchService.getInstance();
24
- }
25
- static get serviceType() {
26
- return ServiceType.WEB_SEARCH;
12
+ ## Recent Conversation
13
+ ${conversationContext}
14
+
15
+ ## Task
16
+ Extract the search query and parameters from the conversation above. The user wants to search the web for information.
17
+
18
+ ## Instructions
19
+ - Determine the exact search query the user wants
20
+ - If the topic is about crypto, DeFi, finance, or markets, set topic to "finance"
21
+ - Only include optional parameters if clearly indicated by the user
22
+
23
+ Respond ONLY with the following XML format:
24
+ <response>
25
+ <reasoning>
26
+ Step 1: Identify what information the user is looking for
27
+ Step 2: Determine the best search query to find this information
28
+ Step 3: Classify the topic based on the subject matter
29
+ </reasoning>
30
+ <query>the exact query to search</query>
31
+ <topic>general or finance</topic>
32
+ </response>`;
33
+ }
34
+ function MaxTokens(data, maxTokens = DEFAULT_MAX_WEB_SEARCH_CHARS) {
35
+ return data.length > maxTokens ? data.slice(0, maxTokens) : data;
36
+ }
37
+ async function extractSearchParams(runtime, message, _state) {
38
+ var _a, _b, _c, _d, _e, _f, _g, _h;
39
+ const composedState = await runtime.composeState(
40
+ message,
41
+ ["ACTION_STATE"],
42
+ true
43
+ );
44
+ const stateParams = ((_a = composedState == null ? void 0 : composedState.data) == null ? void 0 : _a.actionParams) || ((_b = composedState == null ? void 0 : composedState.data) == null ? void 0 : _b.webSearch) || ((_c = composedState == null ? void 0 : composedState.data) == null ? void 0 : _c.websearch) || {};
45
+ if ((_d = stateParams == null ? void 0 : stateParams.query) == null ? void 0 : _d.trim()) {
46
+ logger.info(
47
+ { src: "webSearch:extractParams", source: "actionParams" },
48
+ "Using params from state"
49
+ );
50
+ return stateParams;
27
51
  }
28
- async search(query, options) {
29
- try {
30
- const response = await this.tavilyClient.search(query, {
31
- includeAnswer: options?.includeAnswer || true,
32
- maxResults: options?.limit || 3,
33
- topic: options?.type || "general",
34
- searchDepth: options?.searchDepth || "basic",
35
- includeImages: options?.includeImages || false,
36
- days: options?.days || 3
37
- });
38
- return response;
39
- } catch (error) {
40
- console.error("Web search error:", error);
41
- throw error;
52
+ logger.info(
53
+ { src: "webSearch:extractParams", source: "llm" },
54
+ "Extracting params via LLM"
55
+ );
56
+ try {
57
+ const extractionState = await runtime.composeState(
58
+ message,
59
+ ["RECENT_MESSAGES"],
60
+ true
61
+ );
62
+ const conversationLog = (_e = extractionState == null ? void 0 : extractionState.values) == null ? void 0 : _e.conversationLog;
63
+ const recentMessages = (_f = extractionState == null ? void 0 : extractionState.values) == null ? void 0 : _f.recentMessages;
64
+ const conversationContext = typeof conversationLog === "string" && conversationLog.trim() || typeof recentMessages === "string" && recentMessages.trim() || "";
65
+ const contextSource = typeof conversationLog === "string" && conversationLog.trim() ? "conversationLog" : "recentMessages";
66
+ logger.debug(
67
+ { src: "webSearch:extractParams", contextSource },
68
+ "Using conversation context"
69
+ );
70
+ const template = buildExtractionTemplate(conversationContext);
71
+ const prompt = composePromptFromState({
72
+ state: extractionState,
73
+ template
74
+ });
75
+ const response = await runtime.useModel(ModelType.TEXT_SMALL, { prompt });
76
+ const parsed = parseKeyValueXml(response || "");
77
+ if (parsed == null ? void 0 : parsed.query) {
78
+ const extractedParams = {
79
+ query: String(parsed.query).trim(),
80
+ topic: parsed.topic === "finance" ? "finance" : "general"
81
+ };
82
+ logger.info(
83
+ { src: "webSearch:extractParams", query: extractedParams.query },
84
+ "Extracted query via LLM"
85
+ );
86
+ return extractedParams;
42
87
  }
88
+ } catch (err) {
89
+ logger.warn(
90
+ { src: "webSearch:extractParams", error: err.message },
91
+ "LLM extraction failed, falling back to message text"
92
+ );
43
93
  }
44
- };
45
-
46
- // src/actions/webSearch.ts
47
- var DEFAULT_MAX_WEB_SEARCH_TOKENS = 4e3;
48
- var DEFAULT_MODEL_ENCODING = "gpt-3.5-turbo";
49
- function getTotalTokensFromString(str, encodingName = DEFAULT_MODEL_ENCODING) {
50
- const encoding = encodingForModel(encodingName);
51
- return encoding.encode(str).length;
52
- }
53
- function MaxTokens(data, maxTokens = DEFAULT_MAX_WEB_SEARCH_TOKENS) {
54
- if (getTotalTokensFromString(data) >= maxTokens) {
55
- return data.slice(0, maxTokens);
94
+ const messageText = (_h = (_g = message.content) == null ? void 0 : _g.text) == null ? void 0 : _h.trim();
95
+ if (messageText) {
96
+ logger.info(
97
+ { src: "webSearch:extractParams", source: "messageText" },
98
+ "Using message text as query"
99
+ );
100
+ return { query: messageText };
56
101
  }
57
- return data;
102
+ return {};
58
103
  }
59
104
  var webSearch = {
60
105
  name: "WEB_SEARCH",
@@ -70,48 +115,217 @@ var webSearch = {
70
115
  "FIND_INFORMATION"
71
116
  ],
72
117
  suppressInitialMessage: true,
73
- description: "Perform a web search to find information related to the message.",
74
- // eslint-disable-next-line
75
- validate: async (runtime, message) => {
76
- const tavilyApiKeyOk = !!runtime.getSetting("TAVILY_API_KEY");
77
- return tavilyApiKeyOk;
118
+ description: "Search the web using Tavily. Supports general web search and finance topics (crypto/DeFi/markets). Use when other actions/providers can't provide accurate or current info.\n\nIMPORTANT - Result Quality Check:\n- If search returns off-topic or poor results, RETRY with parameter adjustments in the SAME round\n- Try: topic='finance' for crypto/markets, source filter (theblock.com, coindesk.com), broader time_range, advanced search_depth, or rephrased query\n- For crypto/DeFi content: use topic='finance' + source from [theblock.com, coindesk.com, decrypt.co, dlnews.com]\n- Don't give up after one attempt if results are clearly irrelevant",
119
+ // Parameter schema for tool calling
120
+ parameters: {
121
+ query: {
122
+ type: "string",
123
+ description: "The search query to look up on the web",
124
+ required: true
125
+ },
126
+ topic: {
127
+ type: "string",
128
+ description: "Search topic: 'general' for web search, 'finance' for financial/crypto/DeFi content. Defaults to 'general'.",
129
+ required: false
130
+ },
131
+ source: {
132
+ type: "string",
133
+ description: "Specific source domain to limit results (e.g., 'bloomberg.com', 'reuters.com'). Uses site: operator.",
134
+ required: false
135
+ },
136
+ max_results: {
137
+ type: "number",
138
+ description: "Maximum number of results to return (1-20). Defaults to 5.",
139
+ required: false
140
+ },
141
+ search_depth: {
142
+ type: "string",
143
+ description: "Search depth: 'basic' for quick results or 'advanced' for comprehensive search. Defaults to 'basic'.",
144
+ required: false
145
+ },
146
+ time_range: {
147
+ type: "string",
148
+ description: "Time range filter: 'day', 'week', 'month', 'year' (or 'd', 'w', 'm', 'y')",
149
+ required: false
150
+ },
151
+ start_date: {
152
+ type: "string",
153
+ description: "Start date filter in YYYY-MM-DD format (returns results after this date)",
154
+ required: false
155
+ },
156
+ end_date: {
157
+ type: "string",
158
+ description: "End date filter in YYYY-MM-DD format (returns results before this date)",
159
+ required: false
160
+ }
78
161
  },
79
- handler: async (runtime, message, state, options, callback) => {
80
- elizaLogger.log("Composing state for message:", message);
81
- state = await runtime.composeState(message);
82
- const userId = runtime.agentId;
83
- elizaLogger.log("User ID:", userId);
84
- const webSearchPrompt = message.content.text;
85
- elizaLogger.log("web search prompt received:", webSearchPrompt);
86
- const webSearchService = new WebSearchService();
87
- await webSearchService.initialize(runtime);
88
- const searchResponse = await webSearchService.search(
89
- webSearchPrompt
90
- );
91
- if (searchResponse && searchResponse.results.length) {
92
- const responseList = searchResponse.answer ? `${searchResponse.answer}${Array.isArray(searchResponse.results) && searchResponse.results.length > 0 ? `
162
+ validate: async (runtime, _message, _state) => {
163
+ try {
164
+ const service = runtime.getService("TAVILY");
165
+ return !!service;
166
+ } catch (err) {
167
+ logger.warn(
168
+ { src: "webSearch:validate", error: err.message },
169
+ "TavilyService not available"
170
+ );
171
+ return false;
172
+ }
173
+ },
174
+ handler: async (runtime, message, state, _options, callback) => {
175
+ var _a, _b;
176
+ try {
177
+ const tavilyService = runtime.getService("TAVILY");
178
+ if (!tavilyService) {
179
+ throw new Error("TavilyService not initialized");
180
+ }
181
+ const params = await extractSearchParams(runtime, message, state);
182
+ const query = (_a = params == null ? void 0 : params.query) == null ? void 0 : _a.trim();
183
+ if (!query) {
184
+ const errorMsg = "Missing required parameter 'query'. Please specify what to search for.";
185
+ logger.error({ src: "webSearch:handler" }, errorMsg);
186
+ const emptyResult = {
187
+ text: errorMsg,
188
+ success: false,
189
+ data: {
190
+ actionName: "WEB_SEARCH"
191
+ },
192
+ error: "missing_required_parameter"
193
+ };
194
+ if (callback) {
195
+ callback({
196
+ text: emptyResult.text,
197
+ content: { error: "missing_required_parameter", details: errorMsg }
198
+ });
199
+ }
200
+ return emptyResult;
201
+ }
202
+ const source = (_b = params == null ? void 0 : params.source) == null ? void 0 : _b.trim();
203
+ const topic = (params == null ? void 0 : params.topic) === "finance" ? "finance" : "general";
204
+ const maxResults = (params == null ? void 0 : params.max_results) ? Math.min(Math.max(1, params.max_results), 20) : 5;
205
+ const searchDepth = (params == null ? void 0 : params.search_depth) === "advanced" ? "advanced" : "basic";
206
+ let enhancedQuery = query;
207
+ if (source) {
208
+ enhancedQuery = `${query} site:${source}`;
209
+ logger.info(
210
+ { src: "webSearch:handler", source },
211
+ "Searching with source filter"
212
+ );
213
+ }
214
+ logger.info(
215
+ { src: "webSearch:handler", query: enhancedQuery, topic },
216
+ "Executing web search"
217
+ );
218
+ const inputParams = {
219
+ query,
220
+ topic,
221
+ source,
222
+ max_results: maxResults,
223
+ search_depth: searchDepth,
224
+ time_range: params == null ? void 0 : params.time_range,
225
+ start_date: params == null ? void 0 : params.start_date,
226
+ end_date: params == null ? void 0 : params.end_date
227
+ };
228
+ const searchResponse = await tavilyService.search(enhancedQuery, {
229
+ topic,
230
+ max_results: maxResults,
231
+ search_depth: searchDepth,
232
+ time_range: params == null ? void 0 : params.time_range,
233
+ start_date: params == null ? void 0 : params.start_date,
234
+ end_date: params == null ? void 0 : params.end_date,
235
+ include_answer: true,
236
+ include_images: false
237
+ });
238
+ if (searchResponse && searchResponse.results.length) {
239
+ const responseList = searchResponse.answer ? `${searchResponse.answer}${Array.isArray(searchResponse.results) && searchResponse.results.length > 0 ? `
93
240
 
94
241
  For more details, you can check out these resources:
95
242
  ${searchResponse.results.map(
96
- (result, index) => `${index + 1}. [${result.title}](${result.url})`
97
- ).join("\n")}` : ""}` : "";
98
- callback({
99
- text: MaxTokens(responseList, DEFAULT_MAX_WEB_SEARCH_TOKENS)
100
- });
101
- } else {
102
- elizaLogger.error("search failed or returned no data.");
243
+ (result2, index) => `${index + 1}. [${result2.title}](${result2.url})`
244
+ ).join("\n")}` : ""}` : "";
245
+ const result = {
246
+ text: MaxTokens(responseList, DEFAULT_MAX_WEB_SEARCH_CHARS),
247
+ success: true,
248
+ data: {
249
+ ...searchResponse,
250
+ actionName: "WEB_SEARCH"
251
+ },
252
+ input: inputParams
253
+ };
254
+ if (callback) {
255
+ callback({
256
+ text: result.text,
257
+ actions: ["WEB_SEARCH"],
258
+ data: result.data
259
+ });
260
+ }
261
+ return result;
262
+ }
263
+ const noResult = {
264
+ text: "I couldn't find relevant results for that query.",
265
+ success: false,
266
+ data: {
267
+ actionName: "WEB_SEARCH"
268
+ },
269
+ input: inputParams
270
+ };
271
+ if (callback) {
272
+ callback({ text: noResult.text });
273
+ }
274
+ return noResult;
275
+ } catch (error) {
276
+ const errMsg = error instanceof Error ? error.message : String(error);
277
+ logger.error(
278
+ { src: "webSearch:handler", error: errMsg },
279
+ "Action failed"
280
+ );
281
+ const errorResult = {
282
+ text: `Web search failed: ${errMsg}`,
283
+ success: false,
284
+ data: {
285
+ actionName: "WEB_SEARCH"
286
+ },
287
+ error: errMsg
288
+ };
289
+ if (callback) {
290
+ callback({
291
+ text: errorResult.text,
292
+ content: { error: "web_search_failed", details: errMsg }
293
+ });
294
+ }
295
+ return errorResult;
103
296
  }
104
297
  },
105
298
  examples: [
106
299
  [
107
300
  {
108
- user: "{{user1}}",
301
+ name: "{{user}}",
302
+ content: {
303
+ text: "Latest Aave news"
304
+ }
305
+ },
306
+ {
307
+ name: "{{agent}}",
308
+ content: {
309
+ text: "Let me search for Aave news from crypto sources:",
310
+ action: "WEB_SEARCH",
311
+ actionParams: {
312
+ query: "Aave protocol",
313
+ topic: "finance",
314
+ source: "theblock.com",
315
+ time_range: "week"
316
+ }
317
+ }
318
+ }
319
+ ],
320
+ [
321
+ {
322
+ name: "{{user}}",
109
323
  content: {
110
324
  text: "Find the latest news about SpaceX launches."
111
325
  }
112
326
  },
113
327
  {
114
- user: "{{agentName}}",
328
+ name: "{{agent}}",
115
329
  content: {
116
330
  text: "Here is the latest news about SpaceX launches:",
117
331
  action: "WEB_SEARCH"
@@ -120,13 +334,13 @@ ${searchResponse.results.map(
120
334
  ],
121
335
  [
122
336
  {
123
- user: "{{user1}}",
337
+ name: "{{user}}",
124
338
  content: {
125
339
  text: "Can you find details about the iPhone 16 release?"
126
340
  }
127
341
  },
128
342
  {
129
- user: "{{agentName}}",
343
+ name: "{{agent}}",
130
344
  content: {
131
345
  text: "Here are the details I found about the iPhone 16 release:",
132
346
  action: "WEB_SEARCH"
@@ -135,13 +349,13 @@ ${searchResponse.results.map(
135
349
  ],
136
350
  [
137
351
  {
138
- user: "{{user1}}",
352
+ name: "{{user}}",
139
353
  content: {
140
354
  text: "What is the schedule for the next FIFA World Cup?"
141
355
  }
142
356
  },
143
357
  {
144
- user: "{{agentName}}",
358
+ name: "{{agent}}",
145
359
  content: {
146
360
  text: "Here is the schedule for the next FIFA World Cup:",
147
361
  action: "WEB_SEARCH"
@@ -150,11 +364,11 @@ ${searchResponse.results.map(
150
364
  ],
151
365
  [
152
366
  {
153
- user: "{{user1}}",
367
+ name: "{{user}}",
154
368
  content: { text: "Check the latest stock price of Tesla." }
155
369
  },
156
370
  {
157
- user: "{{agentName}}",
371
+ name: "{{agent}}",
158
372
  content: {
159
373
  text: "Here is the latest stock price of Tesla I found:",
160
374
  action: "WEB_SEARCH"
@@ -163,13 +377,13 @@ ${searchResponse.results.map(
163
377
  ],
164
378
  [
165
379
  {
166
- user: "{{user1}}",
380
+ name: "{{user}}",
167
381
  content: {
168
382
  text: "What are the current trending movies in the US?"
169
383
  }
170
384
  },
171
385
  {
172
- user: "{{agentName}}",
386
+ name: "{{agent}}",
173
387
  content: {
174
388
  text: "Here are the current trending movies in the US:",
175
389
  action: "WEB_SEARCH"
@@ -178,13 +392,13 @@ ${searchResponse.results.map(
178
392
  ],
179
393
  [
180
394
  {
181
- user: "{{user1}}",
395
+ name: "{{user}}",
182
396
  content: {
183
397
  text: "What is the latest score in the NBA finals?"
184
398
  }
185
399
  },
186
400
  {
187
- user: "{{agentName}}",
401
+ name: "{{agent}}",
188
402
  content: {
189
403
  text: "Here is the latest score from the NBA finals:",
190
404
  action: "WEB_SEARCH"
@@ -193,11 +407,11 @@ ${searchResponse.results.map(
193
407
  ],
194
408
  [
195
409
  {
196
- user: "{{user1}}",
410
+ name: "{{user}}",
197
411
  content: { text: "When is the next Apple keynote event?" }
198
412
  },
199
413
  {
200
- user: "{{agentName}}",
414
+ name: "{{agent}}",
201
415
  content: {
202
416
  text: "Here is the information about the next Apple keynote event:",
203
417
  action: "WEB_SEARCH"
@@ -207,15 +421,76 @@ ${searchResponse.results.map(
207
421
  ]
208
422
  };
209
423
 
424
+ // src/services/tavilyService.ts
425
+ import { logger as logger2, Service } from "@elizaos/core";
426
+ import { tavily } from "@tavily/core";
427
+ var TavilyService = class _TavilyService extends Service {
428
+ static serviceType = "TAVILY";
429
+ tavilyClient;
430
+ constructor(runtime) {
431
+ super(runtime);
432
+ }
433
+ static async start(runtime) {
434
+ const service = new _TavilyService(runtime);
435
+ await service.initialize(runtime);
436
+ return service;
437
+ }
438
+ async initialize(runtime) {
439
+ const apiKey = runtime.getSetting("TAVILY_API_KEY");
440
+ if (!apiKey) {
441
+ throw new Error("TAVILY_API_KEY is not set");
442
+ }
443
+ this.tavilyClient = tavily({ apiKey });
444
+ }
445
+ get capabilityDescription() {
446
+ return "Web search via Tavily API. Supports answer synthesis and result listing with optional images.";
447
+ }
448
+ async stop() {
449
+ }
450
+ async search(query, options) {
451
+ try {
452
+ if (!this.tavilyClient) {
453
+ throw new Error("TavilyService not initialized");
454
+ }
455
+ const response = await this.tavilyClient.search(query, {
456
+ auto_parameters: options == null ? void 0 : options.auto_parameters,
457
+ topic: (options == null ? void 0 : options.topic) ?? "general",
458
+ search_depth: (options == null ? void 0 : options.search_depth) ?? "basic",
459
+ chunks_per_source: options == null ? void 0 : options.chunks_per_source,
460
+ max_results: (options == null ? void 0 : options.max_results) ?? 5,
461
+ time_range: options == null ? void 0 : options.time_range,
462
+ start_date: options == null ? void 0 : options.start_date,
463
+ end_date: options == null ? void 0 : options.end_date,
464
+ include_answer: (options == null ? void 0 : options.include_answer) ?? false,
465
+ include_raw_content: options == null ? void 0 : options.include_raw_content,
466
+ include_images: (options == null ? void 0 : options.include_images) ?? false,
467
+ include_image_descriptions: options == null ? void 0 : options.include_image_descriptions,
468
+ include_favicon: options == null ? void 0 : options.include_favicon,
469
+ include_domains: options == null ? void 0 : options.include_domains,
470
+ exclude_domains: options == null ? void 0 : options.exclude_domains,
471
+ country: options == null ? void 0 : options.country
472
+ });
473
+ return response;
474
+ } catch (error) {
475
+ logger2.error(
476
+ { src: "tavilyService:search", error: error.message },
477
+ "Tavily search error"
478
+ );
479
+ throw error;
480
+ }
481
+ }
482
+ };
483
+
210
484
  // src/index.ts
211
485
  var webSearchPlugin = {
212
486
  name: "webSearch",
213
- description: "Search the web and get news",
487
+ description: "Search the web using Tavily",
214
488
  actions: [webSearch],
215
489
  evaluators: [],
216
490
  providers: [],
217
- services: [new WebSearchService()],
218
- clients: []
491
+ services: [TavilyService],
492
+ clients: [],
493
+ adapters: []
219
494
  };
220
495
  var index_default = webSearchPlugin;
221
496
  export {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/actions/webSearch.ts","../src/services/webSearchService.ts","../src/index.ts"],"sourcesContent":["import {\n type Action,\n type HandlerCallback,\n type IAgentRuntime,\n type Memory,\n type State,\n elizaLogger\n} from \"@elizaos/core\";\nimport { encodingForModel, type TiktokenModel } from \"js-tiktoken\";\nimport { WebSearchService } from \"../services/webSearchService\";\nimport type { SearchResult } from \"../types\";\n\nconst DEFAULT_MAX_WEB_SEARCH_TOKENS = 4000;\nconst DEFAULT_MODEL_ENCODING = \"gpt-3.5-turbo\";\n\nfunction getTotalTokensFromString(\n str: string,\n encodingName: TiktokenModel = DEFAULT_MODEL_ENCODING\n) {\n const encoding = encodingForModel(encodingName);\n return encoding.encode(str).length;\n}\n\nfunction MaxTokens(\n data: string,\n maxTokens: number = DEFAULT_MAX_WEB_SEARCH_TOKENS\n): string {\n if (getTotalTokensFromString(data) >= maxTokens) {\n return data.slice(0, maxTokens);\n }\n return data;\n}\n\nexport const webSearch: Action = {\n name: \"WEB_SEARCH\",\n similes: [\n \"SEARCH_WEB\",\n \"INTERNET_SEARCH\",\n \"LOOKUP\",\n \"QUERY_WEB\",\n \"FIND_ONLINE\",\n \"SEARCH_ENGINE\",\n \"WEB_LOOKUP\",\n \"ONLINE_SEARCH\",\n \"FIND_INFORMATION\",\n ],\n suppressInitialMessage: true,\n description:\n \"Perform a web search to find information related to the message.\",\n // eslint-disable-next-line\n validate: async (runtime: IAgentRuntime, message: Memory) => {\n const tavilyApiKeyOk = !!runtime.getSetting(\"TAVILY_API_KEY\");\n\n return tavilyApiKeyOk;\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State,\n options: any,\n callback: HandlerCallback\n ) => {\n elizaLogger.log(\"Composing state for message:\", message);\n state = (await runtime.composeState(message)) as State;\n const userId = runtime.agentId;\n elizaLogger.log(\"User ID:\", userId);\n\n const webSearchPrompt = message.content.text;\n elizaLogger.log(\"web search prompt received:\", webSearchPrompt);\n\n const webSearchService = new WebSearchService();\n await webSearchService.initialize(runtime);\n const searchResponse = await webSearchService.search(\n webSearchPrompt,\n );\n\n if (searchResponse && searchResponse.results.length) {\n const responseList = searchResponse.answer\n ? `${searchResponse.answer}${\n Array.isArray(searchResponse.results) &&\n searchResponse.results.length > 0\n ? `\\n\\nFor more details, you can check out these resources:\\n${searchResponse.results\n .map(\n (result: SearchResult, index: number) =>\n `${index + 1}. [${result.title}](${result.url})`\n )\n .join(\"\\n\")}`\n : \"\"\n }`\n : \"\";\n\n callback({\n text: MaxTokens(responseList, DEFAULT_MAX_WEB_SEARCH_TOKENS),\n });\n } else {\n elizaLogger.error(\"search failed or returned no data.\");\n }\n },\n examples: [\n [\n {\n user: \"{{user1}}\",\n content: {\n text: \"Find the latest news about SpaceX launches.\",\n },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here is the latest news about SpaceX launches:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: {\n text: \"Can you find details about the iPhone 16 release?\",\n },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here are the details I found about the iPhone 16 release:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: {\n text: \"What is the schedule for the next FIFA World Cup?\",\n },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here is the schedule for the next FIFA World Cup:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: { text: \"Check the latest stock price of Tesla.\" },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here is the latest stock price of Tesla I found:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: {\n text: \"What are the current trending movies in the US?\",\n },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here are the current trending movies in the US:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: {\n text: \"What is the latest score in the NBA finals?\",\n },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here is the latest score from the NBA finals:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n user: \"{{user1}}\",\n content: { text: \"When is the next Apple keynote event?\" },\n },\n {\n user: \"{{agentName}}\",\n content: {\n text: \"Here is the information about the next Apple keynote event:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n ],\n} as Action;","import {\n Service,\n type IAgentRuntime,\n ServiceType,\n} from \"@elizaos/core\";\nimport { tavily } from \"@tavily/core\";\nimport type { IWebSearchService, SearchOptions, SearchResponse } from \"../types\";\n\nexport type TavilyClient = ReturnType<typeof tavily>; // declaring manually because original package does not export its types\n\nexport class WebSearchService extends Service implements IWebSearchService {\n public tavilyClient: TavilyClient\n\n async initialize(_runtime: IAgentRuntime): Promise<void> {\n const apiKey = _runtime.getSetting(\"TAVILY_API_KEY\") as string;\n if (!apiKey) {\n throw new Error(\"TAVILY_API_KEY is not set\");\n }\n this.tavilyClient = tavily({ apiKey });\n }\n\n getInstance(): IWebSearchService {\n return WebSearchService.getInstance();\n }\n\n static get serviceType(): ServiceType {\n return ServiceType.WEB_SEARCH;\n }\n\n async search(\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResponse> {\n try {\n const response = await this.tavilyClient.search(query, {\n includeAnswer: options?.includeAnswer || true,\n maxResults: options?.limit || 3,\n topic: options?.type || \"general\",\n searchDepth: options?.searchDepth || \"basic\",\n includeImages: options?.includeImages || false,\n days: options?.days || 3,\n });\n\n return response;\n } catch (error) {\n console.error(\"Web search error:\", error);\n throw error;\n }\n }\n}\n","import { webSearch } from \"./actions/webSearch\";\nimport type { Plugin } from \"@elizaos/core\";\nimport { WebSearchService } from \"./services/webSearchService\";\n\nexport const webSearchPlugin: Plugin = {\n name: \"webSearch\",\n description: \"Search the web and get news\",\n actions: [webSearch],\n evaluators: [],\n providers: [],\n services: [new WebSearchService()],\n clients: [],\n};\n\nexport default webSearchPlugin;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/actions/webSearch.ts","../src/services/tavilyService.ts","../src/index.ts"],"sourcesContent":["import {\n type ActionResult,\n type HandlerCallback,\n type IAgentRuntime,\n type Memory,\n type State,\n logger,\n Action,\n ModelType,\n composePromptFromState,\n parseKeyValueXml,\n} from \"@elizaos/core\";\nimport { TavilyService } from \"../services/tavilyService\";\nimport type { SearchResult } from \"../types\";\n\ninterface WebSearchParams {\n query?: string;\n topic?: string;\n source?: string;\n max_results?: number;\n search_depth?: string;\n time_range?: \"day\" | \"week\" | \"month\" | \"year\" | \"d\" | \"w\" | \"m\" | \"y\";\n start_date?: string;\n end_date?: string;\n}\n\nconst DEFAULT_MAX_WEB_SEARCH_CHARS = 16000;\n\n/**\n * Build the extraction template with the appropriate conversation context.\n * Prefers conversationLog if available, falls back to recentMessages.\n */\nfunction buildExtractionTemplate(conversationContext: string): string {\n return `# Web Search Parameter Extraction\n\n## Recent Conversation\n${conversationContext}\n\n## Task\nExtract the search query and parameters from the conversation above. The user wants to search the web for information.\n\n## Instructions\n- Determine the exact search query the user wants\n- If the topic is about crypto, DeFi, finance, or markets, set topic to \"finance\"\n- Only include optional parameters if clearly indicated by the user\n\nRespond ONLY with the following XML format:\n<response>\n <reasoning>\n Step 1: Identify what information the user is looking for\n Step 2: Determine the best search query to find this information\n Step 3: Classify the topic based on the subject matter\n </reasoning>\n <query>the exact query to search</query>\n <topic>general or finance</topic>\n</response>`;\n}\n\nfunction MaxTokens(\n data: string,\n maxTokens: number = DEFAULT_MAX_WEB_SEARCH_CHARS,\n): string {\n // Character-based truncation to cap response length\n return data.length > maxTokens ? data.slice(0, maxTokens) : data;\n}\n\n/**\n * Extract search parameters from state or via LLM.\n * Supports multiple runtime patterns:\n * 1. actionParams from custom bootstrap (otaku pattern)\n * 2. LLM extraction from conversation context (eliza-cloud-v2, elizav2)\n */\nasync function extractSearchParams(\n runtime: IAgentRuntime,\n message: Memory,\n _state: State,\n): Promise<WebSearchParams> {\n // First, try to get params from state (custom bootstrap pattern)\n const composedState = await runtime.composeState(\n message,\n [\"ACTION_STATE\"],\n true,\n );\n\n const stateParams = (composedState?.data?.actionParams ||\n composedState?.data?.webSearch ||\n composedState?.data?.websearch ||\n {}) as WebSearchParams;\n\n // If we have a query from state, use it\n if (stateParams?.query?.trim()) {\n logger.info(\n { src: \"webSearch:extractParams\", source: \"actionParams\" },\n \"Using params from state\",\n );\n return stateParams;\n }\n\n // Otherwise, extract from conversation using LLM\n logger.info(\n { src: \"webSearch:extractParams\", source: \"llm\" },\n \"Extracting params via LLM\",\n );\n\n try {\n // Compose state - try to get both conversationLog and recentMessages\n const extractionState = await runtime.composeState(\n message,\n [\"RECENT_MESSAGES\"],\n true,\n );\n\n // Prefer conversationLog if available, fallback to recentMessages\n const conversationLog = extractionState?.values?.conversationLog;\n const recentMessages = extractionState?.values?.recentMessages;\n\n const conversationContext =\n (typeof conversationLog === \"string\" && conversationLog.trim()) ||\n (typeof recentMessages === \"string\" && recentMessages.trim()) ||\n \"\";\n\n const contextSource =\n typeof conversationLog === \"string\" && conversationLog.trim()\n ? \"conversationLog\"\n : \"recentMessages\";\n\n logger.debug(\n { src: \"webSearch:extractParams\", contextSource },\n \"Using conversation context\",\n );\n\n const template = buildExtractionTemplate(conversationContext);\n const prompt = composePromptFromState({\n state: extractionState,\n template,\n });\n\n const response = await runtime.useModel(ModelType.TEXT_SMALL, { prompt });\n const parsed = parseKeyValueXml(response || \"\");\n\n if (parsed?.query) {\n const extractedParams: WebSearchParams = {\n query: String(parsed.query).trim(),\n topic:\n parsed.topic === \"finance\"\n ? \"finance\"\n : (\"general\" as \"general\" | \"finance\"),\n };\n\n logger.info(\n { src: \"webSearch:extractParams\", query: extractedParams.query },\n \"Extracted query via LLM\",\n );\n\n return extractedParams;\n }\n } catch (err) {\n logger.warn(\n { src: \"webSearch:extractParams\", error: (err as Error).message },\n \"LLM extraction failed, falling back to message text\",\n );\n }\n\n // Final fallback: use the message text directly as the query\n const messageText = message.content?.text?.trim();\n if (messageText) {\n logger.info(\n { src: \"webSearch:extractParams\", source: \"messageText\" },\n \"Using message text as query\",\n );\n return { query: messageText };\n }\n\n return {};\n}\n\nexport const webSearch: Action = {\n name: \"WEB_SEARCH\",\n similes: [\n \"SEARCH_WEB\",\n \"INTERNET_SEARCH\",\n \"LOOKUP\",\n \"QUERY_WEB\",\n \"FIND_ONLINE\",\n \"SEARCH_ENGINE\",\n \"WEB_LOOKUP\",\n \"ONLINE_SEARCH\",\n \"FIND_INFORMATION\",\n ],\n suppressInitialMessage: true,\n description:\n \"Search the web using Tavily. Supports general web search and finance topics (crypto/DeFi/markets). Use when other actions/providers can't provide accurate or current info.\\n\\n\" +\n \"IMPORTANT - Result Quality Check:\\n\" +\n \"- If search returns off-topic or poor results, RETRY with parameter adjustments in the SAME round\\n\" +\n \"- Try: topic='finance' for crypto/markets, source filter (theblock.com, coindesk.com), broader time_range, advanced search_depth, or rephrased query\\n\" +\n \"- For crypto/DeFi content: use topic='finance' + source from [theblock.com, coindesk.com, decrypt.co, dlnews.com]\\n\" +\n \"- Don't give up after one attempt if results are clearly irrelevant\",\n\n // Parameter schema for tool calling\n parameters: {\n query: {\n type: \"string\",\n description: \"The search query to look up on the web\",\n required: true,\n },\n topic: {\n type: \"string\",\n description:\n \"Search topic: 'general' for web search, 'finance' for financial/crypto/DeFi content. Defaults to 'general'.\",\n required: false,\n },\n source: {\n type: \"string\",\n description:\n \"Specific source domain to limit results (e.g., 'bloomberg.com', 'reuters.com'). Uses site: operator.\",\n required: false,\n },\n max_results: {\n type: \"number\",\n description: \"Maximum number of results to return (1-20). Defaults to 5.\",\n required: false,\n },\n search_depth: {\n type: \"string\",\n description:\n \"Search depth: 'basic' for quick results or 'advanced' for comprehensive search. Defaults to 'basic'.\",\n required: false,\n },\n time_range: {\n type: \"string\",\n description:\n \"Time range filter: 'day', 'week', 'month', 'year' (or 'd', 'w', 'm', 'y')\",\n required: false,\n },\n start_date: {\n type: \"string\",\n description:\n \"Start date filter in YYYY-MM-DD format (returns results after this date)\",\n required: false,\n },\n end_date: {\n type: \"string\",\n description:\n \"End date filter in YYYY-MM-DD format (returns results before this date)\",\n required: false,\n },\n },\n\n validate: async (\n runtime: IAgentRuntime,\n _message: Memory,\n _state?: State,\n ) => {\n try {\n const service = runtime.getService<TavilyService>(\"TAVILY\");\n return !!service;\n } catch (err) {\n logger.warn(\n { src: \"webSearch:validate\", error: (err as Error).message },\n \"TavilyService not available\",\n );\n return false;\n }\n },\n handler: async (\n runtime: IAgentRuntime,\n message: Memory,\n state: State,\n _options?: { [key: string]: unknown },\n callback?: HandlerCallback,\n ): Promise<ActionResult> => {\n try {\n const tavilyService = runtime.getService<TavilyService>(\"TAVILY\");\n if (!tavilyService) {\n throw new Error(\"TavilyService not initialized\");\n }\n\n // Extract parameters (supports multiple runtime patterns)\n const params = await extractSearchParams(runtime, message, state);\n\n // Extract and validate query parameter (required)\n const query: string | undefined = params?.query?.trim();\n\n if (!query) {\n const errorMsg =\n \"Missing required parameter 'query'. Please specify what to search for.\";\n logger.error({ src: \"webSearch:handler\" }, errorMsg);\n const emptyResult: ActionResult = {\n text: errorMsg,\n success: false,\n data: {\n actionName: \"WEB_SEARCH\",\n },\n error: \"missing_required_parameter\",\n };\n if (callback) {\n callback({\n text: emptyResult.text,\n content: { error: \"missing_required_parameter\", details: errorMsg },\n });\n }\n return emptyResult;\n }\n\n const source = params?.source?.trim();\n const topic = params?.topic === \"finance\" ? \"finance\" : \"general\";\n const maxResults = params?.max_results\n ? Math.min(Math.max(1, params.max_results), 20)\n : 5;\n const searchDepth =\n params?.search_depth === \"advanced\" ? \"advanced\" : \"basic\";\n\n // Build enhanced query with source if provided\n let enhancedQuery = query;\n if (source) {\n enhancedQuery = `${query} site:${source}`;\n logger.info(\n { src: \"webSearch:handler\", source },\n \"Searching with source filter\",\n );\n }\n\n logger.info(\n { src: \"webSearch:handler\", query: enhancedQuery, topic },\n \"Executing web search\",\n );\n\n // Store input parameters for return\n const inputParams = {\n query,\n topic,\n source,\n max_results: maxResults,\n search_depth: searchDepth,\n time_range: params?.time_range,\n start_date: params?.start_date,\n end_date: params?.end_date,\n };\n\n // Use provided parameters or defaults\n const searchResponse = await tavilyService.search(enhancedQuery, {\n topic,\n max_results: maxResults,\n search_depth: searchDepth,\n time_range: params?.time_range,\n start_date: params?.start_date,\n end_date: params?.end_date,\n include_answer: true,\n include_images: false,\n });\n\n if (searchResponse && searchResponse.results.length) {\n const responseList = searchResponse.answer\n ? `${searchResponse.answer}${\n Array.isArray(searchResponse.results) &&\n searchResponse.results.length > 0\n ? `\\n\\nFor more details, you can check out these resources:\\n${searchResponse.results\n .map(\n (result: SearchResult, index: number) =>\n `${index + 1}. [${result.title}](${result.url})`,\n )\n .join(\"\\n\")}`\n : \"\"\n }`\n : \"\";\n\n const result: ActionResult = {\n text: MaxTokens(responseList, DEFAULT_MAX_WEB_SEARCH_CHARS),\n success: true,\n data: {\n ...searchResponse,\n actionName: \"WEB_SEARCH\",\n },\n input: inputParams,\n } as ActionResult & { input: typeof inputParams };\n\n if (callback) {\n callback({\n text: result.text,\n actions: [\"WEB_SEARCH\"],\n data: result.data,\n });\n }\n\n return result;\n }\n\n const noResult: ActionResult = {\n text: \"I couldn't find relevant results for that query.\",\n success: false,\n data: {\n actionName: \"WEB_SEARCH\",\n },\n input: inputParams,\n } as ActionResult & { input: typeof inputParams };\n\n if (callback) {\n callback({ text: noResult.text });\n }\n return noResult;\n } catch (error) {\n const errMsg = error instanceof Error ? error.message : String(error);\n logger.error(\n { src: \"webSearch:handler\", error: errMsg },\n \"Action failed\",\n );\n\n const errorResult: ActionResult = {\n text: `Web search failed: ${errMsg}`,\n success: false,\n data: {\n actionName: \"WEB_SEARCH\",\n },\n error: errMsg,\n };\n\n if (callback) {\n callback({\n text: errorResult.text,\n content: { error: \"web_search_failed\", details: errMsg },\n });\n }\n return errorResult;\n }\n },\n examples: [\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"Latest Aave news\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Let me search for Aave news from crypto sources:\",\n action: \"WEB_SEARCH\",\n actionParams: {\n query: \"Aave protocol\",\n topic: \"finance\",\n source: \"theblock.com\",\n time_range: \"week\",\n },\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"Find the latest news about SpaceX launches.\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here is the latest news about SpaceX launches:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"Can you find details about the iPhone 16 release?\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here are the details I found about the iPhone 16 release:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"What is the schedule for the next FIFA World Cup?\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here is the schedule for the next FIFA World Cup:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: { text: \"Check the latest stock price of Tesla.\" },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here is the latest stock price of Tesla I found:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"What are the current trending movies in the US?\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here are the current trending movies in the US:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: {\n text: \"What is the latest score in the NBA finals?\",\n },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here is the latest score from the NBA finals:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n [\n {\n name: \"{{user}}\",\n content: { text: \"When is the next Apple keynote event?\" },\n },\n {\n name: \"{{agent}}\",\n content: {\n text: \"Here is the information about the next Apple keynote event:\",\n action: \"WEB_SEARCH\",\n },\n },\n ],\n ],\n};\n","import { IAgentRuntime, logger, Service } from \"@elizaos/core\";\nimport { tavily } from \"@tavily/core\";\nimport type { ITavilyService, SearchOptions, SearchResponse } from \"../types\";\n\nexport type TavilyClient = ReturnType<typeof tavily>;\n\nexport class TavilyService extends Service implements ITavilyService {\n static serviceType = \"TAVILY\" as const;\n\n private tavilyClient!: TavilyClient;\n\n constructor(runtime: IAgentRuntime) {\n super(runtime);\n }\n\n static async start(runtime: IAgentRuntime): Promise<TavilyService> {\n const service = new TavilyService(runtime);\n await service.initialize(runtime);\n return service;\n }\n\n async initialize(runtime: IAgentRuntime): Promise<void> {\n const apiKey = runtime.getSetting(\"TAVILY_API_KEY\") as string;\n if (!apiKey) {\n throw new Error(\"TAVILY_API_KEY is not set\");\n }\n this.tavilyClient = tavily({ apiKey });\n }\n\n get capabilityDescription(): string {\n return \"Web search via Tavily API. Supports answer synthesis and result listing with optional images.\";\n }\n\n async stop(): Promise<void> {\n // No persistent connections to close for Tavily client\n }\n\n async search(\n query: string,\n options?: SearchOptions,\n ): Promise<SearchResponse> {\n try {\n if (!this.tavilyClient) {\n throw new Error(\"TavilyService not initialized\");\n }\n\n const response = await this.tavilyClient.search(query, {\n auto_parameters: options?.auto_parameters,\n topic: options?.topic ?? \"general\",\n search_depth: options?.search_depth ?? \"basic\",\n chunks_per_source: options?.chunks_per_source,\n max_results: options?.max_results ?? 5,\n time_range: options?.time_range,\n start_date: options?.start_date,\n end_date: options?.end_date,\n include_answer: options?.include_answer ?? false,\n include_raw_content: options?.include_raw_content,\n include_images: options?.include_images ?? false,\n include_image_descriptions: options?.include_image_descriptions,\n include_favicon: options?.include_favicon,\n include_domains: options?.include_domains,\n exclude_domains: options?.exclude_domains,\n country: options?.country,\n });\n\n return response;\n } catch (error) {\n logger.error(\n { src: \"tavilyService:search\", error: (error as Error).message },\n \"Tavily search error\",\n );\n throw error;\n }\n }\n}\n","import { webSearch } from \"./actions/webSearch\";\nimport { TavilyService } from \"./services/tavilyService\";\n\nexport const webSearchPlugin = {\n name: \"webSearch\",\n description: \"Search the web using Tavily\",\n actions: [webSearch],\n evaluators: [],\n providers: [],\n services: [TavilyService],\n clients: [],\n adapters: [],\n};\n\nexport default webSearchPlugin;\n"],"mappings":"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","names":["result","logger"]}
package/package.json CHANGED
@@ -1,36 +1,57 @@
1
1
  {
2
- "name": "@elizaos/plugin-web-search",
3
- "version": "0.1.9",
4
- "type": "module",
5
- "main": "dist/index.js",
6
- "module": "dist/index.js",
7
- "types": "dist/index.d.ts",
8
- "exports": {
9
- "./package.json": "./package.json",
10
- ".": {
11
- "import": {
12
- "@elizaos/source": "./src/index.ts",
13
- "types": "./dist/index.d.ts",
14
- "default": "./dist/index.js"
15
- }
16
- }
17
- },
18
- "files": [
19
- "dist"
20
- ],
21
- "dependencies": {
22
- "@elizaos/core": "0.1.9",
23
- "@tavily/core": "^0.0.2",
24
- "js-tiktoken": "1.0.15",
25
- "tsup": "8.3.5"
26
- },
27
- "scripts": {
28
- "build": "tsup --format esm --dts",
29
- "dev": "tsup --format esm --dts --watch",
30
- "lint": "eslint --fix --cache ."
31
- },
32
- "peerDependencies": {
33
- "whatwg-url": "7.1.0"
34
- },
35
- "gitHead": "ffa4c1dcdacc096d5b451f246b53fbaa266b0f64"
2
+ "name": "@elizaos/plugin-web-search",
3
+ "version": "1.0.1",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ "./package.json": "./package.json",
10
+ ".": {
11
+ "import": {
12
+ "@elizaos/source": "./src/index.ts",
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ }
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "dependencies": {
22
+ "@tavily/core": "0.5.13"
23
+ },
24
+ "devDependencies": {
25
+ "@elizaos/config": "1.6.5",
26
+ "@eslint/js": "^9.17.0",
27
+ "@typescript-eslint/eslint-plugin": "^8.22.0",
28
+ "@typescript-eslint/parser": "^8.22.0",
29
+ "eslint": "^9.17.0",
30
+ "prettier": "3.5.3",
31
+ "tsup": "8.4.0"
32
+ },
33
+ "peerDependencies": {
34
+ "@elizaos/core": "1.7.0",
35
+ "whatwg-url": "7.1.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup --format esm --dts",
39
+ "dev": "tsup --format esm --dts --watch",
40
+ "lint": "eslint ./src --fix && prettier --write ./src",
41
+ "lint:check": "eslint ./src",
42
+ "format": "prettier --write ./src",
43
+ "format:fix": "prettier --write ./src"
44
+ },
45
+ "publishConfig": {
46
+ "access": "public"
47
+ },
48
+ "agentConfig": {
49
+ "pluginType": "elizaos:client:1.0.0",
50
+ "pluginParameters": {
51
+ "TAVILY_API_KEY": {
52
+ "type": "string",
53
+ "description": "Tavily API key for accessing news services"
54
+ }
55
+ }
56
+ }
36
57
  }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Shaw Walters, aka Moon aka @lalalune
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.