@agentforge/tools 0.3.9 → 0.4.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.
- package/README.md +93 -7
- package/dist/index.cjs +354 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +248 -1
- package/dist/index.d.ts +248 -1
- package/dist/index.js +347 -1
- package/dist/index.js.map +1 -1
- package/package.json +16 -16
- package/LICENSE +0 -22
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @agentforge/tools
|
|
2
2
|
|
|
3
|
-
> Production-ready tools collection for AgentForge -
|
|
3
|
+
> Production-ready tools collection for AgentForge - 69 tools for web, data, file, and utility operations
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@agentforge/tools)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## 🎉 Status: Production Ready & Published
|
|
10
10
|
|
|
11
|
-
**
|
|
11
|
+
**69 production-ready tools** | **Full TypeScript support** | **Comprehensive documentation** | **LangChain compatible**
|
|
12
12
|
|
|
13
13
|
## 📦 Installation
|
|
14
14
|
|
|
@@ -22,9 +22,9 @@ yarn add @agentforge/tools
|
|
|
22
22
|
|
|
23
23
|
## 🎯 Overview
|
|
24
24
|
|
|
25
|
-
This package provides **
|
|
25
|
+
This package provides **69 ready-to-use tools** organized into 4 categories:
|
|
26
26
|
|
|
27
|
-
- **🌐 Web Tools** (
|
|
27
|
+
- **🌐 Web Tools** (11 tools) - HTTP requests, web search, web scraping, HTML parsing, URL manipulation
|
|
28
28
|
- **📊 Data Tools** (18 tools) - JSON, CSV, XML processing and data transformation
|
|
29
29
|
- **📁 File Tools** (18 tools) - File operations, directory management, path utilities
|
|
30
30
|
- **🔧 Utility Tools** (22 tools) - Date/time, strings, math, validation
|
|
@@ -68,10 +68,17 @@ const result = await calculator.execute({
|
|
|
68
68
|
|
|
69
69
|
## 📚 Tool Categories
|
|
70
70
|
|
|
71
|
-
### 🌐 Web Tools (
|
|
71
|
+
### 🌐 Web Tools (11 tools)
|
|
72
72
|
|
|
73
73
|
Tools for web interactions and HTTP operations.
|
|
74
74
|
|
|
75
|
+
#### Web Search
|
|
76
|
+
- **`webSearch`** - Search the web using DuckDuckGo (free) or Serper API (optional premium)
|
|
77
|
+
- No API key required for basic searches (uses DuckDuckGo)
|
|
78
|
+
- Optional Serper API for premium Google search results
|
|
79
|
+
- Smart fallback: automatically switches providers when needed
|
|
80
|
+
- Returns structured results with titles, links, and snippets
|
|
81
|
+
|
|
75
82
|
#### HTTP Client Tools
|
|
76
83
|
- **`httpClient`** - Full-featured HTTP client with all methods (GET, POST, PUT, DELETE, PATCH)
|
|
77
84
|
- **`httpGet`** - Simple GET requests
|
|
@@ -182,6 +189,85 @@ General utility tools for common operations.
|
|
|
182
189
|
|
|
183
190
|
## 💡 Usage Examples
|
|
184
191
|
|
|
192
|
+
### Web Search Example
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
import { webSearch } from '@agentforge/tools';
|
|
196
|
+
|
|
197
|
+
// Basic search (no API key needed - uses DuckDuckGo)
|
|
198
|
+
const result = await webSearch.execute({
|
|
199
|
+
query: 'TypeScript programming language',
|
|
200
|
+
maxResults: 10
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
console.log(`Found ${result.results.length} results from ${result.source}`);
|
|
204
|
+
result.results.forEach(r => {
|
|
205
|
+
console.log(`${r.title}: ${r.link}`);
|
|
206
|
+
console.log(` ${r.snippet}`);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Premium search with Serper API (requires SERPER_API_KEY env var)
|
|
210
|
+
// Get your API key at: https://serper.dev
|
|
211
|
+
const premiumResult = await webSearch.execute({
|
|
212
|
+
query: 'Latest AI developments 2026',
|
|
213
|
+
maxResults: 5,
|
|
214
|
+
preferSerper: true // Use Serper for Google search results
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Check metadata
|
|
218
|
+
console.log(`Source: ${premiumResult.source}`);
|
|
219
|
+
console.log(`Fallback used: ${premiumResult.metadata?.fallbackUsed}`);
|
|
220
|
+
console.log(`Response time: ${premiumResult.metadata?.responseTime}ms`);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**Environment Setup:**
|
|
224
|
+
```bash
|
|
225
|
+
# Optional: Add to your .env file for premium Google search
|
|
226
|
+
SERPER_API_KEY=your-serper-api-key-here
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**Input Schema:**
|
|
230
|
+
```typescript
|
|
231
|
+
{
|
|
232
|
+
query: string; // Search query (required)
|
|
233
|
+
maxResults?: number; // Max results to return (default: 10)
|
|
234
|
+
preferSerper?: boolean; // Prefer Serper over DuckDuckGo (default: false)
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
**Output Schema:**
|
|
239
|
+
```typescript
|
|
240
|
+
{
|
|
241
|
+
results: Array<{
|
|
242
|
+
title: string; // Result title
|
|
243
|
+
link: string; // Result URL
|
|
244
|
+
snippet: string; // Result description/snippet
|
|
245
|
+
position: number; // Result position (1-based)
|
|
246
|
+
}>;
|
|
247
|
+
source: 'duckduckgo' | 'serper'; // Which provider was used
|
|
248
|
+
metadata?: {
|
|
249
|
+
fallbackUsed: boolean; // Whether fallback to DuckDuckGo occurred
|
|
250
|
+
responseTime: number; // Response time in milliseconds
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**DuckDuckGo vs Serper:**
|
|
256
|
+
|
|
257
|
+
| Feature | DuckDuckGo (Free) | Serper (Premium) |
|
|
258
|
+
|---------|-------------------|------------------|
|
|
259
|
+
| **API Key** | ❌ Not required | ✅ Required ([get key](https://serper.dev)) |
|
|
260
|
+
| **Cost** | 🆓 Free | 💰 Paid (see [pricing](https://serper.dev/pricing)) |
|
|
261
|
+
| **Search Engine** | DuckDuckGo | Google |
|
|
262
|
+
| **Rate Limits** | Generous | Based on plan |
|
|
263
|
+
| **Result Quality** | Good | Excellent (Google results) |
|
|
264
|
+
| **Use Case** | Development, testing, low-volume | Production, high-quality results |
|
|
265
|
+
| **Fallback** | N/A | Auto-fallback to DuckDuckGo on error |
|
|
266
|
+
|
|
267
|
+
**When to use each:**
|
|
268
|
+
- **DuckDuckGo**: Default choice, no setup needed, great for development and testing
|
|
269
|
+
- **Serper**: Production use cases requiring Google-quality results, set `preferSerper: true`
|
|
270
|
+
|
|
185
271
|
### Web Scraping Example
|
|
186
272
|
|
|
187
273
|
```typescript
|
|
@@ -435,8 +521,8 @@ pnpm lint
|
|
|
435
521
|
|
|
436
522
|
## 📊 Tool Statistics
|
|
437
523
|
|
|
438
|
-
- **Total Tools**:
|
|
439
|
-
- **Web Tools**:
|
|
524
|
+
- **Total Tools**: 69
|
|
525
|
+
- **Web Tools**: 11
|
|
440
526
|
- **Data Tools**: 18
|
|
441
527
|
- **File Tools**: 18
|
|
442
528
|
- **Utility Tools**: 22
|
package/dist/index.cjs
CHANGED
|
@@ -343,6 +343,352 @@ var urlQueryParser = core.toolBuilder().name("url-query-parser").description("Pa
|
|
|
343
343
|
count: Object.keys(params).length
|
|
344
344
|
};
|
|
345
345
|
}).build();
|
|
346
|
+
var webSearchSchema = zod.z.object({
|
|
347
|
+
query: zod.z.string().min(1).describe("The search query"),
|
|
348
|
+
maxResults: zod.z.number().min(1).max(50).default(10).describe("Maximum number of results to return (1-50)"),
|
|
349
|
+
preferSerper: zod.z.boolean().default(false).describe("Prefer Serper API if available (requires SERPER_API_KEY)"),
|
|
350
|
+
timeout: zod.z.number().min(1e3).max(6e4).default(3e4).describe("Request timeout in milliseconds (1000-60000, default: 30000)")
|
|
351
|
+
});
|
|
352
|
+
var searchResultSchema = zod.z.object({
|
|
353
|
+
title: zod.z.string(),
|
|
354
|
+
link: zod.z.string().url(),
|
|
355
|
+
snippet: zod.z.string(),
|
|
356
|
+
position: zod.z.number().optional()
|
|
357
|
+
});
|
|
358
|
+
var webSearchOutputSchema = zod.z.object({
|
|
359
|
+
success: zod.z.boolean(),
|
|
360
|
+
source: zod.z.enum(["duckduckgo", "serper"]),
|
|
361
|
+
query: zod.z.string(),
|
|
362
|
+
results: zod.z.array(searchResultSchema),
|
|
363
|
+
totalResults: zod.z.number().optional(),
|
|
364
|
+
error: zod.z.string().optional(),
|
|
365
|
+
metadata: zod.z.object({
|
|
366
|
+
responseTime: zod.z.number().optional(),
|
|
367
|
+
fallbackUsed: zod.z.boolean().optional()
|
|
368
|
+
}).optional()
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
// src/web/web-search/utils.ts
|
|
372
|
+
function getSerperApiKey() {
|
|
373
|
+
return process.env.SERPER_API_KEY;
|
|
374
|
+
}
|
|
375
|
+
async function measureTime(fn) {
|
|
376
|
+
const start = Date.now();
|
|
377
|
+
const result = await fn();
|
|
378
|
+
const duration = Date.now() - start;
|
|
379
|
+
return { result, duration };
|
|
380
|
+
}
|
|
381
|
+
function sanitizeQuery(query) {
|
|
382
|
+
return query.trim().replace(/\s+/g, " ");
|
|
383
|
+
}
|
|
384
|
+
var DEFAULT_RETRY_CONFIG = {
|
|
385
|
+
maxRetries: 3,
|
|
386
|
+
initialDelay: 1e3,
|
|
387
|
+
// 1 second
|
|
388
|
+
maxDelay: 1e4,
|
|
389
|
+
// 10 seconds
|
|
390
|
+
backoffMultiplier: 2
|
|
391
|
+
};
|
|
392
|
+
var DEFAULT_TIMEOUT = 3e4;
|
|
393
|
+
function isRetryableError(error) {
|
|
394
|
+
if (error.code === "ECONNRESET" || error.code === "ETIMEDOUT" || error.code === "ENOTFOUND") {
|
|
395
|
+
return true;
|
|
396
|
+
}
|
|
397
|
+
if (error.code === "ECONNABORTED" || error.message?.includes("timeout")) {
|
|
398
|
+
return true;
|
|
399
|
+
}
|
|
400
|
+
if (error.response?.status >= 500 && error.response?.status < 600) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
if (error.response?.status === 429) {
|
|
404
|
+
return true;
|
|
405
|
+
}
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
function sleep(ms) {
|
|
409
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
410
|
+
}
|
|
411
|
+
async function retryWithBackoff(fn, config = DEFAULT_RETRY_CONFIG) {
|
|
412
|
+
let lastError;
|
|
413
|
+
let delay = config.initialDelay;
|
|
414
|
+
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
415
|
+
try {
|
|
416
|
+
return await fn();
|
|
417
|
+
} catch (error) {
|
|
418
|
+
lastError = error;
|
|
419
|
+
if (!isRetryableError(error)) {
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
422
|
+
if (attempt === config.maxRetries) {
|
|
423
|
+
break;
|
|
424
|
+
}
|
|
425
|
+
await sleep(delay);
|
|
426
|
+
delay = Math.min(delay * config.backoffMultiplier, config.maxDelay);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
throw lastError;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// src/web/web-search/providers/duckduckgo.ts
|
|
433
|
+
var DuckDuckGoProvider = class {
|
|
434
|
+
name = "duckduckgo";
|
|
435
|
+
/**
|
|
436
|
+
* DuckDuckGo is always available (no API key required)
|
|
437
|
+
*/
|
|
438
|
+
isAvailable() {
|
|
439
|
+
return true;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Search using DuckDuckGo Instant Answer API
|
|
443
|
+
* @param query - Search query
|
|
444
|
+
* @param maxResults - Maximum number of results to return
|
|
445
|
+
* @param timeout - Request timeout in milliseconds (default: 30000)
|
|
446
|
+
*/
|
|
447
|
+
async search(query, maxResults, timeout = DEFAULT_TIMEOUT) {
|
|
448
|
+
return retryWithBackoff(async () => {
|
|
449
|
+
try {
|
|
450
|
+
const response = await axios__default.default.get(
|
|
451
|
+
"https://api.duckduckgo.com/",
|
|
452
|
+
{
|
|
453
|
+
params: {
|
|
454
|
+
q: query,
|
|
455
|
+
format: "json"
|
|
456
|
+
},
|
|
457
|
+
headers: {
|
|
458
|
+
"User-Agent": "Mozilla/5.0 (compatible; AgentForge/1.0; +https://github.com/agentforge)"
|
|
459
|
+
},
|
|
460
|
+
timeout
|
|
461
|
+
}
|
|
462
|
+
);
|
|
463
|
+
return this.normalizeResults(response.data, maxResults);
|
|
464
|
+
} catch (error) {
|
|
465
|
+
throw new Error(`DuckDuckGo search failed: ${error.message}`);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Normalize DuckDuckGo response to SearchResult[]
|
|
471
|
+
* Optimized for performance with large result sets
|
|
472
|
+
*/
|
|
473
|
+
normalizeResults(data, maxResults) {
|
|
474
|
+
const results = [];
|
|
475
|
+
if (maxResults <= 0) {
|
|
476
|
+
return results;
|
|
477
|
+
}
|
|
478
|
+
if (data.Abstract && data.AbstractURL) {
|
|
479
|
+
results.push({
|
|
480
|
+
title: data.Heading || "Result",
|
|
481
|
+
link: data.AbstractURL,
|
|
482
|
+
snippet: data.Abstract,
|
|
483
|
+
position: 1
|
|
484
|
+
});
|
|
485
|
+
if (results.length >= maxResults) {
|
|
486
|
+
return results;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
if (data.RelatedTopics && data.RelatedTopics.length > 0) {
|
|
490
|
+
const remaining = maxResults - results.length;
|
|
491
|
+
const topicsToProcess = data.RelatedTopics.slice(0, remaining);
|
|
492
|
+
for (const topic of topicsToProcess) {
|
|
493
|
+
if (topic.Text && topic.FirstURL) {
|
|
494
|
+
const titleParts = topic.Text.split(" - ");
|
|
495
|
+
results.push({
|
|
496
|
+
title: titleParts[0] || topic.Text,
|
|
497
|
+
link: topic.FirstURL,
|
|
498
|
+
snippet: topic.Text,
|
|
499
|
+
position: results.length + 1
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (results.length >= maxResults) {
|
|
504
|
+
return results;
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (data.Results && data.Results.length > 0) {
|
|
508
|
+
const remaining = maxResults - results.length;
|
|
509
|
+
const resultsToProcess = data.Results.slice(0, remaining);
|
|
510
|
+
for (const result of resultsToProcess) {
|
|
511
|
+
if (result.Text && result.FirstURL) {
|
|
512
|
+
const titleParts = result.Text.split(" - ");
|
|
513
|
+
results.push({
|
|
514
|
+
title: titleParts[0] || result.Text,
|
|
515
|
+
link: result.FirstURL,
|
|
516
|
+
snippet: result.Text,
|
|
517
|
+
position: results.length + 1
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
return results;
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
function createDuckDuckGoProvider() {
|
|
526
|
+
return new DuckDuckGoProvider();
|
|
527
|
+
}
|
|
528
|
+
var SerperProvider = class {
|
|
529
|
+
name = "serper";
|
|
530
|
+
apiKey;
|
|
531
|
+
constructor() {
|
|
532
|
+
this.apiKey = getSerperApiKey();
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* Serper is available if API key is set
|
|
536
|
+
*/
|
|
537
|
+
isAvailable() {
|
|
538
|
+
return !!this.apiKey;
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Search using Serper API
|
|
542
|
+
* @param query - Search query
|
|
543
|
+
* @param maxResults - Maximum number of results to return
|
|
544
|
+
* @param timeout - Request timeout in milliseconds (default: 30000)
|
|
545
|
+
*/
|
|
546
|
+
async search(query, maxResults, timeout = DEFAULT_TIMEOUT) {
|
|
547
|
+
if (!this.apiKey) {
|
|
548
|
+
throw new Error(
|
|
549
|
+
"Serper API key not found. Set SERPER_API_KEY environment variable. Get your key at https://serper.dev"
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
return retryWithBackoff(async () => {
|
|
553
|
+
try {
|
|
554
|
+
const response = await axios__default.default.post(
|
|
555
|
+
"https://google.serper.dev/search",
|
|
556
|
+
{
|
|
557
|
+
q: query,
|
|
558
|
+
num: maxResults
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
headers: {
|
|
562
|
+
"X-API-KEY": this.apiKey,
|
|
563
|
+
"Content-Type": "application/json"
|
|
564
|
+
},
|
|
565
|
+
timeout
|
|
566
|
+
}
|
|
567
|
+
);
|
|
568
|
+
return this.normalizeResults(response.data, maxResults);
|
|
569
|
+
} catch (error) {
|
|
570
|
+
if (error.response?.status === 401) {
|
|
571
|
+
throw new Error(
|
|
572
|
+
"Invalid Serper API key. Get your key at https://serper.dev"
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
if (error.response?.status === 429) {
|
|
576
|
+
throw new Error(
|
|
577
|
+
"Serper API rate limit exceeded. Please try again later or upgrade your plan at https://serper.dev"
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
throw new Error(`Serper search failed: ${error.message}`);
|
|
581
|
+
}
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Normalize Serper response to SearchResult[]
|
|
586
|
+
* Optimized for performance with large result sets
|
|
587
|
+
*/
|
|
588
|
+
normalizeResults(data, maxResults) {
|
|
589
|
+
if (!data.organic || data.organic.length === 0 || maxResults <= 0) {
|
|
590
|
+
return [];
|
|
591
|
+
}
|
|
592
|
+
const results = [];
|
|
593
|
+
const itemsToProcess = Math.min(data.organic.length, maxResults);
|
|
594
|
+
for (let i = 0; i < itemsToProcess; i++) {
|
|
595
|
+
const item = data.organic[i];
|
|
596
|
+
if (!item.title || !item.link || !item.snippet) {
|
|
597
|
+
continue;
|
|
598
|
+
}
|
|
599
|
+
results.push({
|
|
600
|
+
title: item.title,
|
|
601
|
+
link: item.link,
|
|
602
|
+
snippet: item.snippet,
|
|
603
|
+
position: item.position ?? i + 1
|
|
604
|
+
});
|
|
605
|
+
if (results.length >= maxResults) {
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return results;
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
function createSerperProvider() {
|
|
613
|
+
return new SerperProvider();
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
// src/web/web-search/index.ts
|
|
617
|
+
var webSearch = core.toolBuilder().name("web-search").description(
|
|
618
|
+
"Search the web for information using DuckDuckGo (free) or Serper API (optional). Returns structured search results with titles, links, and snippets. Automatically falls back to Serper if DuckDuckGo returns no results and API key is available."
|
|
619
|
+
).category(core.ToolCategory.WEB).tags(["search", "web", "google", "duckduckgo", "serper", "internet"]).schema(webSearchSchema).implement(async (input) => {
|
|
620
|
+
const {
|
|
621
|
+
query,
|
|
622
|
+
maxResults = 10,
|
|
623
|
+
preferSerper = false,
|
|
624
|
+
timeout = DEFAULT_TIMEOUT
|
|
625
|
+
} = input;
|
|
626
|
+
const sanitizedQuery = sanitizeQuery(query);
|
|
627
|
+
const duckduckgo = createDuckDuckGoProvider();
|
|
628
|
+
const serper = createSerperProvider();
|
|
629
|
+
let primaryProvider;
|
|
630
|
+
let fallbackProvider = null;
|
|
631
|
+
if (preferSerper && serper.isAvailable()) {
|
|
632
|
+
primaryProvider = serper;
|
|
633
|
+
fallbackProvider = duckduckgo;
|
|
634
|
+
} else {
|
|
635
|
+
primaryProvider = duckduckgo;
|
|
636
|
+
fallbackProvider = serper.isAvailable() ? serper : null;
|
|
637
|
+
}
|
|
638
|
+
try {
|
|
639
|
+
const { result: results, duration } = await measureTime(
|
|
640
|
+
() => primaryProvider.search(sanitizedQuery, maxResults, timeout)
|
|
641
|
+
);
|
|
642
|
+
if (results.length > 0) {
|
|
643
|
+
return {
|
|
644
|
+
success: true,
|
|
645
|
+
source: primaryProvider.name,
|
|
646
|
+
query: sanitizedQuery,
|
|
647
|
+
results,
|
|
648
|
+
totalResults: results.length,
|
|
649
|
+
metadata: {
|
|
650
|
+
responseTime: duration,
|
|
651
|
+
fallbackUsed: false
|
|
652
|
+
}
|
|
653
|
+
};
|
|
654
|
+
}
|
|
655
|
+
if (fallbackProvider) {
|
|
656
|
+
const { result: fallbackResults, duration: fallbackDuration } = await measureTime(
|
|
657
|
+
() => fallbackProvider.search(sanitizedQuery, maxResults, timeout)
|
|
658
|
+
);
|
|
659
|
+
return {
|
|
660
|
+
success: true,
|
|
661
|
+
source: fallbackProvider.name,
|
|
662
|
+
query: sanitizedQuery,
|
|
663
|
+
results: fallbackResults,
|
|
664
|
+
totalResults: fallbackResults.length,
|
|
665
|
+
metadata: {
|
|
666
|
+
responseTime: fallbackDuration,
|
|
667
|
+
fallbackUsed: true
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
return {
|
|
672
|
+
success: true,
|
|
673
|
+
source: primaryProvider.name,
|
|
674
|
+
query: sanitizedQuery,
|
|
675
|
+
results: [],
|
|
676
|
+
totalResults: 0,
|
|
677
|
+
metadata: {
|
|
678
|
+
responseTime: duration,
|
|
679
|
+
fallbackUsed: false
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
} catch (error) {
|
|
683
|
+
return {
|
|
684
|
+
success: false,
|
|
685
|
+
source: primaryProvider.name,
|
|
686
|
+
query: sanitizedQuery,
|
|
687
|
+
results: [],
|
|
688
|
+
error: error.message
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
}).build();
|
|
346
692
|
var jsonParser = core.toolBuilder().name("json-parser").description("Parse JSON string into an object. Validates JSON syntax and returns parsed data or error details.").category(core.ToolCategory.UTILITY).tags(["json", "parse", "data"]).schema(zod.z.object({
|
|
347
693
|
json: zod.z.string().describe("JSON string to parse"),
|
|
348
694
|
strict: zod.z.boolean().default(true).describe("Use strict JSON parsing (no trailing commas, etc.)")
|
|
@@ -1648,11 +1994,15 @@ var uuidValidator = core.toolBuilder().name("uuid-validator").description("Valid
|
|
|
1648
1994
|
};
|
|
1649
1995
|
}).build();
|
|
1650
1996
|
|
|
1997
|
+
exports.DuckDuckGoProvider = DuckDuckGoProvider;
|
|
1998
|
+
exports.SerperProvider = SerperProvider;
|
|
1651
1999
|
exports.arrayFilter = arrayFilter;
|
|
1652
2000
|
exports.arrayGroupBy = arrayGroupBy;
|
|
1653
2001
|
exports.arrayMap = arrayMap;
|
|
1654
2002
|
exports.arraySort = arraySort;
|
|
1655
2003
|
exports.calculator = calculator;
|
|
2004
|
+
exports.createDuckDuckGoProvider = createDuckDuckGoProvider;
|
|
2005
|
+
exports.createSerperProvider = createSerperProvider;
|
|
1656
2006
|
exports.creditCardValidator = creditCardValidator;
|
|
1657
2007
|
exports.csvGenerator = csvGenerator;
|
|
1658
2008
|
exports.csvParser = csvParser;
|
|
@@ -1699,6 +2049,7 @@ exports.pathRelative = pathRelative;
|
|
|
1699
2049
|
exports.pathResolve = pathResolve;
|
|
1700
2050
|
exports.phoneValidator = phoneValidator;
|
|
1701
2051
|
exports.randomNumber = randomNumber;
|
|
2052
|
+
exports.searchResultSchema = searchResultSchema;
|
|
1702
2053
|
exports.statistics = statistics;
|
|
1703
2054
|
exports.stringCaseConverter = stringCaseConverter;
|
|
1704
2055
|
exports.stringJoin = stringJoin;
|
|
@@ -1713,6 +2064,9 @@ exports.urlValidator = urlValidator;
|
|
|
1713
2064
|
exports.urlValidatorSimple = urlValidatorSimple;
|
|
1714
2065
|
exports.uuidValidator = uuidValidator;
|
|
1715
2066
|
exports.webScraper = webScraper;
|
|
2067
|
+
exports.webSearch = webSearch;
|
|
2068
|
+
exports.webSearchOutputSchema = webSearchOutputSchema;
|
|
2069
|
+
exports.webSearchSchema = webSearchSchema;
|
|
1716
2070
|
exports.xmlGenerator = xmlGenerator;
|
|
1717
2071
|
exports.xmlParser = xmlParser;
|
|
1718
2072
|
exports.xmlToJson = xmlToJson;
|