@scavio/ai-sdk 0.4.0 → 0.5.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 +70 -11
- package/dist/index.cjs +144 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +111 -2
- package/dist/index.d.ts +111 -2
- package/dist/index.js +139 -3
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/README.md
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Scavio search and page-extraction tools for the [Vercel AI SDK](https://sdk.vercel.ai). Give any AI
|
|
4
4
|
SDK agent real-time search across Google, YouTube, Reddit, Amazon, Walmart, TikTok, and Instagram --
|
|
5
|
-
plus `scavio_extract`, which reads any URL -- via the [Scavio](https://scavio.dev) API.
|
|
5
|
+
plus `scavio_extract`, which reads any URL, and opt-in tools that map, crawl or batch-extract whole sites -- via the [Scavio](https://scavio.dev) API.
|
|
6
6
|
|
|
7
7
|
**This package exposes a curated subset of the Scavio API**, chosen for agent
|
|
8
|
-
use: 13 tools -- 12 over 7 platforms, plus the core `extract` endpoint, which
|
|
9
|
-
belongs to no platform. The full surface is 195 endpoints across 31 platforms,
|
|
8
|
+
use: 13 tools by default -- 12 over 7 platforms, plus the core `extract` endpoint, which
|
|
9
|
+
belongs to no platform -- and 5 opt-in website tools (map, crawl, batch) on top. The full surface is 195 endpoints across 31 platforms,
|
|
10
10
|
adding X, LinkedIn, TikTok Shop, eBay, Target, Home Depot, Zillow, Redfin,
|
|
11
11
|
Booking, Airbnb, Tripadvisor, Yelp, Indeed, Glassdoor, the App Store, Google
|
|
12
12
|
Play, SEC, Companies House, G2, Capterra, Google Ads, Meta Ad Library, Threads,
|
|
@@ -16,7 +16,7 @@ Trends, AI Mode). To reach all of them, point your agent at the
|
|
|
16
16
|
191 tools over every endpoint, nothing to vendor.
|
|
17
17
|
|
|
18
18
|
Credits are not uniform: most calls cost 1, YouTube search costs 2 and
|
|
19
|
-
transcript costs
|
|
19
|
+
transcript costs 5, Instagram costs 2 to 10 depending on the endpoint, and
|
|
20
20
|
`scavio_extract` is priced by the `mode` you ask for (1 / 1 / 2), not per call.
|
|
21
21
|
|
|
22
22
|
> **Amazon changed (breaking).** The upstream provider moved in 2026-07:
|
|
@@ -68,7 +68,7 @@ const res2 = await generateText({
|
|
|
68
68
|
| `scavioSearch` | `scavio_search` | Google web search, `/api/v2/google` (1 credit) |
|
|
69
69
|
| `scavioYoutubeSearch` | `scavio_youtube_search` | YouTube video search (2 credits) |
|
|
70
70
|
| `scavioYoutubeVideo` | `scavio_youtube_video` | YouTube video details (1 credit) |
|
|
71
|
-
| `scavioYoutubeTranscript` | `scavio_youtube_transcript` | YouTube transcript / subtitles (
|
|
71
|
+
| `scavioYoutubeTranscript` | `scavio_youtube_transcript` | YouTube transcript / subtitles (5 credits) |
|
|
72
72
|
| `scavioYoutubeComments` | `scavio_youtube_comments` | YouTube video comments (1 credit) |
|
|
73
73
|
| `scavioYoutubeChannel` | `scavio_youtube_channel` | YouTube channel details (1 credit) |
|
|
74
74
|
| `scavioRedditSearch` | `scavio_reddit_search` | Reddit posts (1 credit) |
|
|
@@ -77,9 +77,14 @@ const res2 = await generateText({
|
|
|
77
77
|
| `scavioWalmartSearch` | `scavio_walmart_search` | Walmart products (1 credit) |
|
|
78
78
|
| `scavioTiktokSearch` | `scavio_tiktok_search` | TikTok videos (1 credit) |
|
|
79
79
|
| `scavioInstagramSearch` | `scavio_instagram_search` | Instagram users (10 credits) |
|
|
80
|
-
| `
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
| `scavioMapWebsite` | `scavio_map_website` | A site's page URLs from its sitemaps and start page, `/api/v1/extract/map` (1 credit on `normal`) |
|
|
81
|
+
| `scavioCrawlWebsite` | `scavio_crawl_website` | Crawl a site from one URL, every page as Markdown / text / HTML (per successful page) |
|
|
82
|
+
| `scavioCrawlStatus` | `scavio_crawl_status` | A crawl's progress and page results, cursor-paged (free) |
|
|
83
|
+
| `scavioBatchExtract` | `scavio_batch_extract` | Extract a list of URLs in one job (per successful page) |
|
|
84
|
+
| `scavioBatchStatus` | `scavio_batch_status` | A batch's progress and page results, cursor-paged (free) |
|
|
85
|
+
| `scavioTools` | all of the above (the five website tools only with `enableCrawl: true`) | bundle for `tools:` |
|
|
86
|
+
|
|
87
|
+
Each factory accepts `{ apiKey?, maxResults?, enableCrawl?, pollIntervalMs?, ...ScavioConfig }`. The key falls back to `SCAVIO_API_KEY`.
|
|
83
88
|
Get a key at [dashboard.scavio.dev](https://dashboard.scavio.dev) - new accounts get 50 free credits, no
|
|
84
89
|
credit card.
|
|
85
90
|
|
|
@@ -101,9 +106,8 @@ const page = await generateText({
|
|
|
101
106
|
```
|
|
102
107
|
|
|
103
108
|
`scavio_extract` takes `url` plus an optional `format` (`markdown` default, `text`, `html`) and
|
|
104
|
-
`mode`. `mode` is the price-bearing param: `normal` is
|
|
105
|
-
|
|
106
|
-
for the hardest bot walls (2 credits). Only a successful read is billed - a dead link, a bot wall or
|
|
109
|
+
`mode`. `mode` is the price-bearing param: `normal` is the standard fetch (1 credit), `advanced`
|
|
110
|
+
renders JavaScript-built pages (1 credit), and `ultra` reaches the hardest pages (2 credits). Only a successful read is billed - a dead link, a bot wall or
|
|
107
111
|
a timeout costs nothing. See [the extract docs](https://scavio.dev/docs/extract).
|
|
108
112
|
|
|
109
113
|
These tools cover the most common surfaces. The full Scavio API - 195 endpoints across 31 platforms
|
|
@@ -113,6 +117,61 @@ Google Play, SEC, Companies House, G2, Capterra, Google Ads, Meta Ad Library, Th
|
|
|
113
117
|
plus `extract` - is available directly through the
|
|
114
118
|
[`scavio`](https://www.npmjs.com/package/scavio) SDK or the [MCP server](https://scavio.dev/docs).
|
|
115
119
|
|
|
120
|
+
## Map, crawl and batch
|
|
121
|
+
|
|
122
|
+
Five opt-in tools for whole sites: `scavioTools()` adds them with
|
|
123
|
+
`enableCrawl: true` (off by default, because a crawl bills per page), and each
|
|
124
|
+
factory works on its own:
|
|
125
|
+
|
|
126
|
+
| Tool | What it does | Credits |
|
|
127
|
+
|---|---|---|
|
|
128
|
+
| `scavio_map_website` | List a site's page URLs from its sitemaps and start page, deduplicated and filtered by path or search words | 1 (normal mode; advanced up to 2, ultra up to 10) |
|
|
129
|
+
| `scavio_crawl_website` | Crawl a site from one URL; every same-site page as Markdown, text or HTML | per successful page |
|
|
130
|
+
| `scavio_crawl_status` | A crawl's progress and page results, cursor-paged | free |
|
|
131
|
+
| `scavio_batch_extract` | Extract a list of URLs (up to 1,000, plan-limited) in one job | per successful page |
|
|
132
|
+
| `scavio_batch_status` | A batch's progress and page results, cursor-paged | free |
|
|
133
|
+
|
|
134
|
+
Map answers in one call. Crawl and batch run as background jobs: the start tool
|
|
135
|
+
posts the job and then **waits up to `wait_seconds` (default 45, max 300)** for
|
|
136
|
+
it to finish, returning the job's status with its first page of results (10 by
|
|
137
|
+
default, `limit` up to 100) either way. A job still `queued` or `running` when
|
|
138
|
+
the wait ends keeps going server-side: read the rest later with the matching
|
|
139
|
+
status tool, the returned `data.id` and `next_cursor`. That keeps an agent turn
|
|
140
|
+
bounded while a large crawl (up to 6 hours) runs on.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import { scavioTools, scavioCrawlWebsite } from "@scavio/ai-sdk";
|
|
144
|
+
|
|
145
|
+
// All tools plus the five website tools:
|
|
146
|
+
const tools = scavioTools({ enableCrawl: true });
|
|
147
|
+
|
|
148
|
+
// Or just the crawler:
|
|
149
|
+
const res = await generateText({
|
|
150
|
+
model: openai("gpt-5.5"),
|
|
151
|
+
tools: { scavio_crawl_website: scavioCrawlWebsite() },
|
|
152
|
+
stopWhen: stepCountIs(3),
|
|
153
|
+
prompt: "Crawl https://hono.dev/docs (25 pages max) and list its middleware guides",
|
|
154
|
+
});
|
|
155
|
+
// The tool returns { data: { id, status: "completed" | "running", pages, credits_used, results, next_cursor } }.
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`pollIntervalMs` (default 3000) sets how often a waiting tool checks its job.
|
|
159
|
+
|
|
160
|
+
**Pricing.** Crawl and batch bill **per successful page** at Extract's price for
|
|
161
|
+
the mode: `normal` (the standard fetch) and `advanced` (renders JavaScript-built
|
|
162
|
+
pages) 1 credit, `ultra` (the hardest pages) 2. Failed and skipped pages are
|
|
163
|
+
free, and if your balance runs out the job stops cleanly with
|
|
164
|
+
`stopped_reason: "insufficient_credits"`. Reading a job is free. Crawl and map
|
|
165
|
+
obey the site's robots.txt, and results are kept for 3 days.
|
|
166
|
+
|
|
167
|
+
**Plan limits** (pages per crawl / active jobs / URLs per batch): Free 10/1/10,
|
|
168
|
+
PAYG 100/1/50, Project 500/2/100, Bootstrap 2,000/3/500, Startup 5,000/5/1,000,
|
|
169
|
+
Growth 10,000/10/1,000.
|
|
170
|
+
|
|
171
|
+
Cancellation, webhooks (signed `Scavio-Signature`) and idempotency keys exist in
|
|
172
|
+
the `scavio` SDK (`extract.cancelCrawl`, `webhook_url`, `idempotencyKey`) and the
|
|
173
|
+
[REST API](https://scavio.dev/docs/extract), but are deliberately not agent tools.
|
|
174
|
+
|
|
116
175
|
## License
|
|
117
176
|
|
|
118
177
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -22,8 +22,13 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
scavioAmazonOffers: () => scavioAmazonOffers,
|
|
24
24
|
scavioAmazonSearch: () => scavioAmazonSearch,
|
|
25
|
+
scavioBatchExtract: () => scavioBatchExtract,
|
|
26
|
+
scavioBatchStatus: () => scavioBatchStatus,
|
|
27
|
+
scavioCrawlStatus: () => scavioCrawlStatus,
|
|
28
|
+
scavioCrawlWebsite: () => scavioCrawlWebsite,
|
|
25
29
|
scavioExtract: () => scavioExtract,
|
|
26
30
|
scavioInstagramSearch: () => scavioInstagramSearch,
|
|
31
|
+
scavioMapWebsite: () => scavioMapWebsite,
|
|
27
32
|
scavioRedditSearch: () => scavioRedditSearch,
|
|
28
33
|
scavioSearch: () => scavioSearch,
|
|
29
34
|
scavioTiktokSearch: () => scavioTiktokSearch,
|
|
@@ -70,7 +75,7 @@ function scavioExtract(config) {
|
|
|
70
75
|
"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page."
|
|
71
76
|
),
|
|
72
77
|
mode: import_zod.z.enum(["normal", "advanced", "ultra"]).optional().describe(
|
|
73
|
-
"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders
|
|
78
|
+
"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders JavaScript-built pages and costs 1, 'ultra' reaches the hardest pages and costs 2. Start on 'normal'."
|
|
74
79
|
)
|
|
75
80
|
}),
|
|
76
81
|
execute: async ({ url, format, mode }) => c.extract({ url, format, mode })
|
|
@@ -133,7 +138,7 @@ function scavioYoutubeVideo(config) {
|
|
|
133
138
|
function scavioYoutubeTranscript(config) {
|
|
134
139
|
const c = client(config);
|
|
135
140
|
return (0, import_ai.tool)({
|
|
136
|
-
description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (
|
|
141
|
+
description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (5 credits).",
|
|
137
142
|
inputSchema: import_zod.z.object({
|
|
138
143
|
video_id: import_zod.z.string().describe("YouTube video id or a full watch URL."),
|
|
139
144
|
language: import_zod.z.string().optional().describe("Transcript language code (default 'en')."),
|
|
@@ -251,6 +256,130 @@ function scavioInstagramSearch(config) {
|
|
|
251
256
|
execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), "users", max)
|
|
252
257
|
});
|
|
253
258
|
}
|
|
259
|
+
var JOB_POLL_INTERVAL_MS = 3e3;
|
|
260
|
+
var JOB_WAIT_DEFAULT_SECONDS = 45;
|
|
261
|
+
var JOB_WAIT_MAX_SECONDS = 300;
|
|
262
|
+
var JOB_RESULTS_DEFAULT_LIMIT = 10;
|
|
263
|
+
var JOB_TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
264
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(() => resolve(), ms));
|
|
265
|
+
async function waitForJob(status, id, waitSeconds, pollMs, query) {
|
|
266
|
+
const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1e3;
|
|
267
|
+
for (; ; ) {
|
|
268
|
+
const remaining = deadline - Date.now();
|
|
269
|
+
if (remaining <= 0) break;
|
|
270
|
+
await sleep(Math.min(pollMs, remaining));
|
|
271
|
+
const probe = await status(id, { limit: 1, include_content: false });
|
|
272
|
+
if (JOB_TERMINAL.has(String(probe?.data?.status))) break;
|
|
273
|
+
}
|
|
274
|
+
return await status(id, query);
|
|
275
|
+
}
|
|
276
|
+
async function startAndWait(start, status, input, pollMs) {
|
|
277
|
+
const created = await start();
|
|
278
|
+
const id = created?.data?.id;
|
|
279
|
+
const wait = input.wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;
|
|
280
|
+
if (!id || wait <= 0) return created;
|
|
281
|
+
const query = { limit: input.limit ?? JOB_RESULTS_DEFAULT_LIMIT };
|
|
282
|
+
if (input.include_content !== void 0) query.include_content = input.include_content;
|
|
283
|
+
return waitForJob(status, id, wait, pollMs, query);
|
|
284
|
+
}
|
|
285
|
+
var MODE_DESCRIPTION = "Fetch tier, and the parameter that sets the price: 'normal' (default) is the standard fetch, 'advanced' renders JavaScript-built pages, 'ultra' reaches the hardest pages.";
|
|
286
|
+
var PATHS_DESCRIPTION = "Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].";
|
|
287
|
+
var JOB_PRICE = "Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.";
|
|
288
|
+
var jobFields = {
|
|
289
|
+
format: import_zod.z.enum(["html", "markdown", "text"]).optional().describe("Format for each page, as on extract (default 'markdown')."),
|
|
290
|
+
mode: import_zod.z.enum(["normal", "advanced", "ultra"]).optional().describe(MODE_DESCRIPTION),
|
|
291
|
+
wait_seconds: import_zod.z.number().int().min(0).max(JOB_WAIT_MAX_SECONDS).optional().describe("Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool."),
|
|
292
|
+
limit: import_zod.z.number().int().min(1).max(100).optional().describe("Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor."),
|
|
293
|
+
include_content: import_zod.z.boolean().optional().describe("Set false to list results without their page content (default true).")
|
|
294
|
+
};
|
|
295
|
+
var jobStatusSchema = import_zod.z.object({
|
|
296
|
+
id: import_zod.z.string().describe("Job id returned when the job was started (data.id)."),
|
|
297
|
+
cursor: import_zod.z.string().optional().describe("next_cursor from the previous response, to read the next page."),
|
|
298
|
+
limit: jobFields.limit,
|
|
299
|
+
status: import_zod.z.enum(["succeeded", "failed", "skipped"]).optional().describe("Only results with this status."),
|
|
300
|
+
include_content: jobFields.include_content
|
|
301
|
+
});
|
|
302
|
+
function scavioMapWebsite(config) {
|
|
303
|
+
const c = client(config);
|
|
304
|
+
return (0, import_ai.tool)({
|
|
305
|
+
description: "List a website's page URLs via the Scavio API, gathered from its sitemaps and its start page, deduplicated, filtered by path or search words and limited: `data.links` [{ url, source, lastmod }], `data.total_found`, `data.truncated`. Pages the site's robots.txt disallows are left out. Use it to find the right pages before extracting or crawling. Costs 1 credit on 'normal'; up to 2 on 'advanced' and up to 10 on 'ultra', priced by what the call needed.",
|
|
306
|
+
inputSchema: import_zod.z.object({
|
|
307
|
+
url: import_zod.z.string().describe("The site to map. A bare host is upgraded to https."),
|
|
308
|
+
search: import_zod.z.string().optional().describe("Only return URLs containing every word of this text (case-insensitive)."),
|
|
309
|
+
limit: import_zod.z.number().int().min(1).max(5e3).optional().describe("Maximum links to return, 1-5000. Default 1000 (or the plan's limit if lower: Free 500, PAYG 1,000, paid plans 5,000)."),
|
|
310
|
+
sitemap: import_zod.z.enum(["include", "only", "skip"]).optional().describe("'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone."),
|
|
311
|
+
include_subdomains: import_zod.z.boolean().optional().describe("Also return URLs on subdomains of the site (default false)."),
|
|
312
|
+
include_paths: import_zod.z.array(import_zod.z.string()).optional().describe("Keep only URLs matching these. " + PATHS_DESCRIPTION),
|
|
313
|
+
exclude_paths: import_zod.z.array(import_zod.z.string()).optional().describe("Drop URLs matching these. " + PATHS_DESCRIPTION),
|
|
314
|
+
ignore_query_parameters: import_zod.z.boolean().optional().describe("Treat URLs that differ only by query string as one URL (default true)."),
|
|
315
|
+
mode: jobFields.mode
|
|
316
|
+
}),
|
|
317
|
+
execute: async (input) => await c.extract.map(input)
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
function scavioCrawlWebsite(config) {
|
|
321
|
+
const c = client(config);
|
|
322
|
+
const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;
|
|
323
|
+
return (0, import_ai.tool)({
|
|
324
|
+
description: "Crawl a website from one start URL via the Scavio API: same-site pages are discovered and extracted breadth-first within the page, depth and path limits, each returned as Markdown, text or HTML. Pages the site's robots.txt disallows are skipped. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_crawl_status with the id later. " + JOB_PRICE,
|
|
325
|
+
inputSchema: import_zod.z.object({
|
|
326
|
+
url: import_zod.z.string().describe("Where the crawl starts. Only pages on the same site are crawled."),
|
|
327
|
+
max_pages: import_zod.z.number().int().min(1).max(1e4).optional().describe("Maximum pages to fetch. Default 100. Plan limits: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000."),
|
|
328
|
+
max_depth: import_zod.z.number().int().min(0).max(10).optional().describe("How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page."),
|
|
329
|
+
include_paths: import_zod.z.array(import_zod.z.string()).optional().describe("Crawl only paths matching these. " + PATHS_DESCRIPTION),
|
|
330
|
+
exclude_paths: import_zod.z.array(import_zod.z.string()).optional().describe("Skip paths matching these. " + PATHS_DESCRIPTION),
|
|
331
|
+
allow_subdomains: import_zod.z.boolean().optional().describe("Also crawl subdomains of the site (default false)."),
|
|
332
|
+
ignore_query_parameters: import_zod.z.boolean().optional().describe("Treat URLs that differ only by query string as one page (default true)."),
|
|
333
|
+
sitemap: import_zod.z.enum(["include", "skip", "only"]).optional().describe("'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links."),
|
|
334
|
+
...jobFields
|
|
335
|
+
}),
|
|
336
|
+
execute: async (input) => {
|
|
337
|
+
const { wait_seconds, limit, include_content, ...body } = input;
|
|
338
|
+
return startAndWait(
|
|
339
|
+
() => c.extract.crawl(body),
|
|
340
|
+
(id, q) => c.extract.crawlStatus(id, q),
|
|
341
|
+
{ wait_seconds, limit, include_content },
|
|
342
|
+
pollMs
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
function scavioCrawlStatus(config) {
|
|
348
|
+
const c = client(config);
|
|
349
|
+
return (0, import_ai.tool)({
|
|
350
|
+
description: "Read a crawl's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, stopped_reason, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the crawl finishes. Free: reading a job costs 0 credits.",
|
|
351
|
+
inputSchema: jobStatusSchema,
|
|
352
|
+
execute: async ({ id, limit, ...q }) => await c.extract.crawlStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
function scavioBatchExtract(config) {
|
|
356
|
+
const c = client(config);
|
|
357
|
+
const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;
|
|
358
|
+
return (0, import_ai.tool)({
|
|
359
|
+
description: "Extract a list of URLs (up to 1,000, plan-limited) in one job via the Scavio API, each returned as Markdown, text or HTML exactly like scavio_extract. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_batch_status with the id later. " + JOB_PRICE,
|
|
360
|
+
inputSchema: import_zod.z.object({
|
|
361
|
+
urls: import_zod.z.array(import_zod.z.string()).min(1).max(1e3).describe("The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000."),
|
|
362
|
+
...jobFields
|
|
363
|
+
}),
|
|
364
|
+
execute: async (input) => {
|
|
365
|
+
const { wait_seconds, limit, include_content, ...body } = input;
|
|
366
|
+
return startAndWait(
|
|
367
|
+
() => c.extract.batch(body),
|
|
368
|
+
(id, q) => c.extract.batchStatus(id, q),
|
|
369
|
+
{ wait_seconds, limit, include_content },
|
|
370
|
+
pollMs
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function scavioBatchStatus(config) {
|
|
376
|
+
const c = client(config);
|
|
377
|
+
return (0, import_ai.tool)({
|
|
378
|
+
description: "Read a batch extract's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the batch finishes. Free: reading a job costs 0 credits.",
|
|
379
|
+
inputSchema: jobStatusSchema,
|
|
380
|
+
execute: async ({ id, limit, ...q }) => await c.extract.batchStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })
|
|
381
|
+
});
|
|
382
|
+
}
|
|
254
383
|
function scavioTools(config) {
|
|
255
384
|
return {
|
|
256
385
|
scavio_extract: scavioExtract(config),
|
|
@@ -265,15 +394,27 @@ function scavioTools(config) {
|
|
|
265
394
|
scavio_amazon_offers: scavioAmazonOffers(config),
|
|
266
395
|
scavio_walmart_search: scavioWalmartSearch(config),
|
|
267
396
|
scavio_tiktok_search: scavioTiktokSearch(config),
|
|
268
|
-
scavio_instagram_search: scavioInstagramSearch(config)
|
|
397
|
+
scavio_instagram_search: scavioInstagramSearch(config),
|
|
398
|
+
...config?.enableCrawl ? {
|
|
399
|
+
scavio_map_website: scavioMapWebsite(config),
|
|
400
|
+
scavio_crawl_website: scavioCrawlWebsite(config),
|
|
401
|
+
scavio_crawl_status: scavioCrawlStatus(config),
|
|
402
|
+
scavio_batch_extract: scavioBatchExtract(config),
|
|
403
|
+
scavio_batch_status: scavioBatchStatus(config)
|
|
404
|
+
} : {}
|
|
269
405
|
};
|
|
270
406
|
}
|
|
271
407
|
// Annotate the CommonJS export names for ESM import in node:
|
|
272
408
|
0 && (module.exports = {
|
|
273
409
|
scavioAmazonOffers,
|
|
274
410
|
scavioAmazonSearch,
|
|
411
|
+
scavioBatchExtract,
|
|
412
|
+
scavioBatchStatus,
|
|
413
|
+
scavioCrawlStatus,
|
|
414
|
+
scavioCrawlWebsite,
|
|
275
415
|
scavioExtract,
|
|
276
416
|
scavioInstagramSearch,
|
|
417
|
+
scavioMapWebsite,
|
|
277
418
|
scavioRedditSearch,
|
|
278
419
|
scavioSearch,
|
|
279
420
|
scavioTiktokSearch,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { Scavio, type ScavioConfig, type GoogleSearchOptions } from \"scavio\";\n\nexport interface ScavioToolConfig extends ScavioConfig {\n /**\n * Max number of items to keep in the tool's result list. Defaults to 10.\n * Trimmed inside `data` on every platform except Google, whose body is flat.\n * Ignored by `scavioExtract`, which returns page content rather than a list.\n */\n maxResults?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\n/**\n * Google is the ONLY family with a flat body: `organic_results` and friends sit\n * at the top level, next to `response_time` / `credits_used` / `credits_remaining`.\n */\nfunction trimFlat(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const list = res[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, [key]: list.slice(0, max) };\n }\n return res;\n}\n\n/**\n * Every non-Google endpoint nests its payload under `data` - the response is\n * `{ data: { products: [...] }, response_time, credits_used, credits_remaining }`.\n * Trimming the top level is therefore a silent no-op, so those tools trim\n * inside `data`.\n */\nfunction trimData(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const data = res.data;\n if (!data || typeof data !== \"object\") return res;\n const list = (data as Record<string, unknown>)[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, data: { ...(data as Record<string, unknown>), [key]: list.slice(0, max) } };\n }\n return res;\n}\n\n/**\n * Read any URL (/api/v1/extract).\n *\n * The one tool here that is not tied to a platform, and the only one `maxResults`\n * does not touch: extract returns page CONTENT, not a result list, so there is\n * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL\n * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.\n *\n * Credits are a function of `mode`, not a per-call constant: \"normal\" 1,\n * \"advanced\" 1, \"ultra\" 2. Only a successful read is billed.\n */\nexport function scavioExtract(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read any web page via the Scavio API and get it back as clean Markdown (default), plain text, or raw HTML. Use it on any URL, including one returned by the search tools. Returns `data.content` alongside `data.url`, `data.format`, `data.mode` and `data.content_length`. Cost depends on `mode`: 1 credit on 'normal' and 'advanced', 2 on 'ultra'; a dead link, bot wall or timeout is not billed.\",\n inputSchema: z.object({\n url: z\n .string()\n .describe(\n \"The page to read (1-2048 characters). http(s) only; a bare host is upgraded to https, and loopback, private, link-local and metadata hosts are rejected.\",\n ),\n format: z\n .enum([\"html\", \"markdown\", \"text\"])\n .optional()\n .describe(\n \"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page.\",\n ),\n mode: z\n .enum([\"normal\", \"advanced\", \"ultra\"])\n .optional()\n .describe(\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders the page in a browser for JS-built sites and costs 1, 'ultra' routes through residential proxies for the hardest bot walls and costs 2. Start on 'normal'.\",\n ),\n }),\n execute: async ({ url, format, mode }) => c.extract({ url, format, mode }),\n });\n}\n\n/** Google web search (/api/v2/google, 1 credit). */\nexport function scavioSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search the web with Google via the Scavio API (1 credit). Returns real-time organic search results, each with a title, link, and snippet, under `organic_results`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n countryCode: z.string().optional().describe('Two-letter country code to localize results, e.g. \"us\".'),\n language: z.string().optional().describe('Two-letter UI language code, e.g. \"en\".'),\n page: z.number().int().optional().describe(\"1-based result page; page 2 starts at result 10.\"),\n device: z.enum([\"desktop\", \"mobile\"]).optional().describe(\"Device to emulate.\"),\n nfpr: z.boolean().optional().describe(\"Disable spelling auto-correction / similar-result substitution when true.\"),\n }),\n execute: async ({ query, countryCode, language, page, device, nfpr }) => {\n const params: GoogleSearchOptions = { query };\n if (countryCode) params.gl = countryCode;\n if (language) params.hl = language;\n if (page && page > 1) params.start = (page - 1) * 10;\n if (device) params.device = device;\n if (nfpr !== undefined) params.nfpr = nfpr;\n return trimFlat(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search (2 credits). */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search YouTube for videos, channels, or playlists via the Scavio API (2 credits). Videos come back under `data.results`, with `data.channels` and `data.playlists` alongside.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n upload_date: z.string().optional().describe(\"Upload date filter, e.g. 'today', 'this_week', 'this_month'.\"),\n type: z.string().optional().describe(\"Result type: 'video', 'channel', 'playlist', 'movie'.\"),\n duration: z.string().optional().describe(\"Duration filter: 'short', 'medium', 'long'.\"),\n sort_by: z.string().optional().describe(\"Sort order: 'relevance', 'date', 'view_count', 'rating'.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, upload_date, type, duration, sort_by, cursor }) =>\n trimData(\n await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor } as Parameters<\n typeof c.youtube.search\n >[0]),\n \"results\",\n max,\n ),\n });\n}\n\n/** YouTube video details (1 credit). */\nexport function scavioYoutubeVideo(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n }),\n execute: async ({ video_id }) => c.youtube.video({ video_id }),\n });\n}\n\n/** YouTube video transcript / subtitles (8 credits). */\nexport function scavioYoutubeTranscript(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube video's transcript or timed subtitles via the Scavio API (8 credits).\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n language: z.string().optional().describe(\"Transcript language code (default 'en').\"),\n format: z.enum([\"text\", \"srt\"]).optional().describe(\"'text' for a plain transcript, 'srt' for timed subtitles.\"),\n }),\n execute: async ({ video_id, language, format }) =>\n c.youtube.transcript({ video_id, language, format } as Parameters<typeof c.youtube.transcript>[0]),\n });\n}\n\n/** YouTube video comments (1 credit). */\nexport function scavioYoutubeComments(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"List comments on a YouTube video via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n cursor: z.string().optional().describe(\"Pagination cursor.\"),\n }),\n execute: async ({ video_id, cursor }) =>\n trimData(\n await c.youtube.comments({ video_id, cursor } as Parameters<typeof c.youtube.comments>[0]),\n \"comments\",\n max,\n ),\n });\n}\n\n/** YouTube channel details (1 credit). */\nexport function scavioYoutubeChannel(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.\",\n inputSchema: z.object({\n channel_id: z.string().describe(\"YouTube channel id, @handle, or channel URL.\"),\n }),\n execute: async ({ channel_id }) => c.youtube.channel({ channel_id }),\n });\n}\n\n/**\n * Reddit post search (1 credit).\n *\n * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or\n * filter by type, so no such input is offered. The API silently ignores those\n * params, which would leave a model believing it had filtered when it had not.\n */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Reddit posts via the Scavio API (1 credit). Returns matching posts under `data.results` with `data.next_cursor` for the next page. Results cannot be sorted or filtered by type.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), \"results\", max),\n });\n}\n\n/**\n * Amazon product search.\n *\n * `domain` was dropped in favour of `country`, a two-letter marketplace code -\n * the upstream provider changed in 2026-07 and no longer takes a domain\n * suffix. It still works on the wire as a deprecated alias, but a model should\n * only ever see one spelling of a param.\n */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ query, country }) =>\n trimData(await c.amazon.search({ query, country }), \"products\", max),\n });\n}\n\n/** Every seller offer for one Amazon ASIN. */\nexport function scavioAmazonOffers(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"List every seller offer for one Amazon ASIN via the Scavio API: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only.\",\n inputSchema: z.object({\n asin: z.string().describe(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ asin, country }) =>\n trimData(await c.amazon.offers({ asin, country }), \"offers\", max),\n });\n}\n\n/** Walmart product search. */\nexport function scavioWalmartSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Walmart for products via the Scavio API. Products come back under `data.products`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trimData(await c.walmart.search({ query }), \"products\", max),\n });\n}\n\n/** TikTok video search. */\nexport function scavioTiktokSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.enum([\"0\", \"1\"]).optional().describe(\"Sort order: '0' relevance, '1' most likes.\"),\n publish_time: z\n .enum([\"0\", \"1\", \"7\", \"30\", \"90\", \"180\"])\n .optional()\n .describe(\"Publish window in days: '0' all time, '1', '7', '30', '90', '180'.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trimData(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\n \"aweme_list\",\n max,\n ),\n });\n}\n\n/** Instagram user search. */\nexport function scavioInstagramSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), \"users\", max),\n });\n}\n\n/**\n * All Scavio tools as an object keyed by tool name, ready to spread into the\n * `tools` option of `generateText` / `streamText`.\n */\nexport function scavioTools(config?: ScavioToolConfig) {\n return {\n scavio_extract: scavioExtract(config),\n scavio_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_youtube_video: scavioYoutubeVideo(config),\n scavio_youtube_transcript: scavioYoutubeTranscript(config),\n scavio_youtube_comments: scavioYoutubeComments(config),\n scavio_youtube_channel: scavioYoutubeChannel(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(config),\n scavio_amazon_offers: scavioAmazonOffers(config),\n scavio_walmart_search: scavioWalmartSearch(config),\n scavio_tiktok_search: scavioTiktokSearch(config),\n scavio_instagram_search: scavioInstagramSearch(config),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { Scavio, type ScavioConfig, type GoogleSearchOptions } from \"scavio\";\n\nexport interface ScavioToolConfig extends ScavioConfig {\n /**\n * Max number of items to keep in the tool's result list. Defaults to 10.\n * Trimmed inside `data` on every platform except Google, whose body is flat.\n * Ignored by `scavioExtract`, which returns page content rather than a list.\n */\n maxResults?: number;\n /**\n * Add the five website tools (map, crawl, crawl status, batch extract, batch\n * status) to `scavioTools()`. Off by default: a crawl bills per page. The\n * individual factories (`scavioCrawlWebsite` and friends) work regardless.\n */\n enableCrawl?: boolean;\n /** Milliseconds between progress polls while a crawl or batch tool waits. Default 3000. */\n pollIntervalMs?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\n/**\n * Google is the ONLY family with a flat body: `organic_results` and friends sit\n * at the top level, next to `response_time` / `credits_used` / `credits_remaining`.\n */\nfunction trimFlat(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const list = res[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, [key]: list.slice(0, max) };\n }\n return res;\n}\n\n/**\n * Every non-Google endpoint nests its payload under `data` - the response is\n * `{ data: { products: [...] }, response_time, credits_used, credits_remaining }`.\n * Trimming the top level is therefore a silent no-op, so those tools trim\n * inside `data`.\n */\nfunction trimData(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const data = res.data;\n if (!data || typeof data !== \"object\") return res;\n const list = (data as Record<string, unknown>)[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, data: { ...(data as Record<string, unknown>), [key]: list.slice(0, max) } };\n }\n return res;\n}\n\n/**\n * Read any URL (/api/v1/extract).\n *\n * The one tool here that is not tied to a platform, and the only one `maxResults`\n * does not touch: extract returns page CONTENT, not a result list, so there is\n * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL\n * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.\n *\n * Credits are a function of `mode`, not a per-call constant: \"normal\" 1,\n * \"advanced\" 1, \"ultra\" 2. Only a successful read is billed.\n */\nexport function scavioExtract(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read any web page via the Scavio API and get it back as clean Markdown (default), plain text, or raw HTML. Use it on any URL, including one returned by the search tools. Returns `data.content` alongside `data.url`, `data.format`, `data.mode` and `data.content_length`. Cost depends on `mode`: 1 credit on 'normal' and 'advanced', 2 on 'ultra'; a dead link, bot wall or timeout is not billed.\",\n inputSchema: z.object({\n url: z\n .string()\n .describe(\n \"The page to read (1-2048 characters). http(s) only; a bare host is upgraded to https, and loopback, private, link-local and metadata hosts are rejected.\",\n ),\n format: z\n .enum([\"html\", \"markdown\", \"text\"])\n .optional()\n .describe(\n \"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page.\",\n ),\n mode: z\n .enum([\"normal\", \"advanced\", \"ultra\"])\n .optional()\n .describe(\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders JavaScript-built pages and costs 1, 'ultra' reaches the hardest pages and costs 2. Start on 'normal'.\",\n ),\n }),\n execute: async ({ url, format, mode }) => c.extract({ url, format, mode }),\n });\n}\n\n/** Google web search (/api/v2/google, 1 credit). */\nexport function scavioSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search the web with Google via the Scavio API (1 credit). Returns real-time organic search results, each with a title, link, and snippet, under `organic_results`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n countryCode: z.string().optional().describe('Two-letter country code to localize results, e.g. \"us\".'),\n language: z.string().optional().describe('Two-letter UI language code, e.g. \"en\".'),\n page: z.number().int().optional().describe(\"1-based result page; page 2 starts at result 10.\"),\n device: z.enum([\"desktop\", \"mobile\"]).optional().describe(\"Device to emulate.\"),\n nfpr: z.boolean().optional().describe(\"Disable spelling auto-correction / similar-result substitution when true.\"),\n }),\n execute: async ({ query, countryCode, language, page, device, nfpr }) => {\n const params: GoogleSearchOptions = { query };\n if (countryCode) params.gl = countryCode;\n if (language) params.hl = language;\n if (page && page > 1) params.start = (page - 1) * 10;\n if (device) params.device = device;\n if (nfpr !== undefined) params.nfpr = nfpr;\n return trimFlat(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search (2 credits). */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search YouTube for videos, channels, or playlists via the Scavio API (2 credits). Videos come back under `data.results`, with `data.channels` and `data.playlists` alongside.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n upload_date: z.string().optional().describe(\"Upload date filter, e.g. 'today', 'this_week', 'this_month'.\"),\n type: z.string().optional().describe(\"Result type: 'video', 'channel', 'playlist', 'movie'.\"),\n duration: z.string().optional().describe(\"Duration filter: 'short', 'medium', 'long'.\"),\n sort_by: z.string().optional().describe(\"Sort order: 'relevance', 'date', 'view_count', 'rating'.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, upload_date, type, duration, sort_by, cursor }) =>\n trimData(\n await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor } as Parameters<\n typeof c.youtube.search\n >[0]),\n \"results\",\n max,\n ),\n });\n}\n\n/** YouTube video details (1 credit). */\nexport function scavioYoutubeVideo(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n }),\n execute: async ({ video_id }) => c.youtube.video({ video_id }),\n });\n}\n\n/** YouTube video transcript / subtitles (5 credits). */\nexport function scavioYoutubeTranscript(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube video's transcript or timed subtitles via the Scavio API (5 credits).\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n language: z.string().optional().describe(\"Transcript language code (default 'en').\"),\n format: z.enum([\"text\", \"srt\"]).optional().describe(\"'text' for a plain transcript, 'srt' for timed subtitles.\"),\n }),\n execute: async ({ video_id, language, format }) =>\n c.youtube.transcript({ video_id, language, format } as Parameters<typeof c.youtube.transcript>[0]),\n });\n}\n\n/** YouTube video comments (1 credit). */\nexport function scavioYoutubeComments(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"List comments on a YouTube video via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n cursor: z.string().optional().describe(\"Pagination cursor.\"),\n }),\n execute: async ({ video_id, cursor }) =>\n trimData(\n await c.youtube.comments({ video_id, cursor } as Parameters<typeof c.youtube.comments>[0]),\n \"comments\",\n max,\n ),\n });\n}\n\n/** YouTube channel details (1 credit). */\nexport function scavioYoutubeChannel(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.\",\n inputSchema: z.object({\n channel_id: z.string().describe(\"YouTube channel id, @handle, or channel URL.\"),\n }),\n execute: async ({ channel_id }) => c.youtube.channel({ channel_id }),\n });\n}\n\n/**\n * Reddit post search (1 credit).\n *\n * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or\n * filter by type, so no such input is offered. The API silently ignores those\n * params, which would leave a model believing it had filtered when it had not.\n */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Reddit posts via the Scavio API (1 credit). Returns matching posts under `data.results` with `data.next_cursor` for the next page. Results cannot be sorted or filtered by type.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), \"results\", max),\n });\n}\n\n/**\n * Amazon product search.\n *\n * `domain` was dropped in favour of `country`, a two-letter marketplace code -\n * the upstream provider changed in 2026-07 and no longer takes a domain\n * suffix. It still works on the wire as a deprecated alias, but a model should\n * only ever see one spelling of a param.\n */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ query, country }) =>\n trimData(await c.amazon.search({ query, country }), \"products\", max),\n });\n}\n\n/** Every seller offer for one Amazon ASIN. */\nexport function scavioAmazonOffers(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"List every seller offer for one Amazon ASIN via the Scavio API: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only.\",\n inputSchema: z.object({\n asin: z.string().describe(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ asin, country }) =>\n trimData(await c.amazon.offers({ asin, country }), \"offers\", max),\n });\n}\n\n/** Walmart product search. */\nexport function scavioWalmartSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Walmart for products via the Scavio API. Products come back under `data.products`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trimData(await c.walmart.search({ query }), \"products\", max),\n });\n}\n\n/** TikTok video search. */\nexport function scavioTiktokSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.enum([\"0\", \"1\"]).optional().describe(\"Sort order: '0' relevance, '1' most likes.\"),\n publish_time: z\n .enum([\"0\", \"1\", \"7\", \"30\", \"90\", \"180\"])\n .optional()\n .describe(\"Publish window in days: '0' all time, '1', '7', '30', '90', '180'.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trimData(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\n \"aweme_list\",\n max,\n ),\n });\n}\n\n/** Instagram user search. */\nexport function scavioInstagramSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), \"users\", max),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Website map, crawl and batch: the multi-page members of the Extract family.\n//\n// Map answers in one call. Crawl and batch are background jobs: the start tools\n// post the job, then wait up to wait_seconds (default 45, max 300) for it to\n// finish, polling progress without page content, and return the job's status\n// with its first page of results either way. A job still running when the wait\n// ends keeps going server-side; read the rest with the matching status tool.\n// ---------------------------------------------------------------------------\n\nconst JOB_POLL_INTERVAL_MS = 3_000;\nconst JOB_WAIT_DEFAULT_SECONDS = 45;\nconst JOB_WAIT_MAX_SECONDS = 300;\nconst JOB_RESULTS_DEFAULT_LIMIT = 10;\nconst JOB_TERMINAL = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\ntype JobQuery = {\n cursor?: string;\n limit?: number;\n status?: \"succeeded\" | \"failed\" | \"skipped\";\n include_content?: boolean;\n};\ntype JobPayload = { data?: { id?: string; status?: string } } & Record<string, unknown>;\ntype JobStatusFn = (id: string, query: JobQuery) => Promise<unknown>;\n\n// lib is ES2022 only (no DOM or Node types); every runtime this targets has setTimeout.\ndeclare const setTimeout: (callback: () => void, ms: number) => unknown;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(() => resolve(), ms));\n\n/** Poll a job (content-free) until it finishes or the wait runs out, then read one results page. */\nasync function waitForJob(\n status: JobStatusFn,\n id: string,\n waitSeconds: number,\n pollMs: number,\n query: JobQuery,\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1000;\n for (;;) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollMs, remaining));\n const probe = (await status(id, { limit: 1, include_content: false })) as JobPayload;\n if (JOB_TERMINAL.has(String(probe?.data?.status))) break;\n }\n return (await status(id, query)) as Record<string, unknown>;\n}\n\n/** Start a job, then wait for it (bounded). wait_seconds 0 returns the 202 payload. */\nasync function startAndWait(\n start: () => Promise<unknown>,\n status: JobStatusFn,\n input: { wait_seconds?: number; limit?: number; include_content?: boolean },\n pollMs: number,\n): Promise<Record<string, unknown>> {\n const created = (await start()) as JobPayload;\n const id = created?.data?.id;\n const wait = input.wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;\n if (!id || wait <= 0) return created;\n const query: JobQuery = { limit: input.limit ?? JOB_RESULTS_DEFAULT_LIMIT };\n if (input.include_content !== undefined) query.include_content = input.include_content;\n return waitForJob(status, id, wait, pollMs, query);\n}\n\nconst MODE_DESCRIPTION =\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is the standard fetch, 'advanced' renders JavaScript-built pages, 'ultra' reaches the hardest pages.\";\nconst PATHS_DESCRIPTION =\n \"Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].\";\nconst JOB_PRICE =\n \"Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.\";\n\nconst jobFields = {\n format: z.enum([\"html\", \"markdown\", \"text\"]).optional().describe(\"Format for each page, as on extract (default 'markdown').\"),\n mode: z.enum([\"normal\", \"advanced\", \"ultra\"]).optional().describe(MODE_DESCRIPTION),\n wait_seconds: z\n .number()\n .int()\n .min(0)\n .max(JOB_WAIT_MAX_SECONDS)\n .optional()\n .describe(\"Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool.\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe(\"Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor.\"),\n include_content: z.boolean().optional().describe(\"Set false to list results without their page content (default true).\"),\n};\n\nconst jobStatusSchema = z.object({\n id: z.string().describe(\"Job id returned when the job was started (data.id).\"),\n cursor: z.string().optional().describe(\"next_cursor from the previous response, to read the next page.\"),\n limit: jobFields.limit,\n status: z.enum([\"succeeded\", \"failed\", \"skipped\"]).optional().describe(\"Only results with this status.\"),\n include_content: jobFields.include_content,\n});\n\n/** Map a website's URLs (/api/v1/extract/map). 1 credit on 'normal'. */\nexport function scavioMapWebsite(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"List a website's page URLs via the Scavio API, gathered from its sitemaps and its start page, deduplicated, filtered by path or search words and limited: `data.links` [{ url, source, lastmod }], `data.total_found`, `data.truncated`. Pages the site's robots.txt disallows are left out. Use it to find the right pages before extracting or crawling. Costs 1 credit on 'normal'; up to 2 on 'advanced' and up to 10 on 'ultra', priced by what the call needed.\",\n inputSchema: z.object({\n url: z.string().describe(\"The site to map. A bare host is upgraded to https.\"),\n search: z.string().optional().describe(\"Only return URLs containing every word of this text (case-insensitive).\"),\n limit: z.number().int().min(1).max(5000).optional().describe(\"Maximum links to return, 1-5000. Default 1000 (or the plan's limit if lower: Free 500, PAYG 1,000, paid plans 5,000).\"),\n sitemap: z.enum([\"include\", \"only\", \"skip\"]).optional().describe(\"'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone.\"),\n include_subdomains: z.boolean().optional().describe(\"Also return URLs on subdomains of the site (default false).\"),\n include_paths: z.array(z.string()).optional().describe(\"Keep only URLs matching these. \" + PATHS_DESCRIPTION),\n exclude_paths: z.array(z.string()).optional().describe(\"Drop URLs matching these. \" + PATHS_DESCRIPTION),\n ignore_query_parameters: z.boolean().optional().describe(\"Treat URLs that differ only by query string as one URL (default true).\"),\n mode: jobFields.mode,\n }),\n execute: async (input) =>\n (await c.extract.map(input as Parameters<typeof c.extract.map>[0])) as unknown as Record<string, unknown>,\n });\n}\n\n/** Crawl a website (/api/v1/extract/crawl), then wait (bounded) for it. */\nexport function scavioCrawlWebsite(config?: ScavioToolConfig) {\n const c = client(config);\n const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;\n return tool({\n description:\n \"Crawl a website from one start URL via the Scavio API: same-site pages are discovered and extracted breadth-first within the page, depth and path limits, each returned as Markdown, text or HTML. Pages the site's robots.txt disallows are skipped. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_crawl_status with the id later. \" +\n JOB_PRICE,\n inputSchema: z.object({\n url: z.string().describe(\"Where the crawl starts. Only pages on the same site are crawled.\"),\n max_pages: z.number().int().min(1).max(10000).optional().describe(\"Maximum pages to fetch. Default 100. Plan limits: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000.\"),\n max_depth: z.number().int().min(0).max(10).optional().describe(\"How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page.\"),\n include_paths: z.array(z.string()).optional().describe(\"Crawl only paths matching these. \" + PATHS_DESCRIPTION),\n exclude_paths: z.array(z.string()).optional().describe(\"Skip paths matching these. \" + PATHS_DESCRIPTION),\n allow_subdomains: z.boolean().optional().describe(\"Also crawl subdomains of the site (default false).\"),\n ignore_query_parameters: z.boolean().optional().describe(\"Treat URLs that differ only by query string as one page (default true).\"),\n sitemap: z.enum([\"include\", \"skip\", \"only\"]).optional().describe(\"'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links.\"),\n ...jobFields,\n }),\n execute: async (input) => {\n const { wait_seconds, limit, include_content, ...body } = input;\n return startAndWait(\n () => c.extract.crawl(body as Parameters<typeof c.extract.crawl>[0]),\n (id, q) => c.extract.crawlStatus(id, q),\n { wait_seconds, limit, include_content },\n pollMs,\n );\n },\n });\n}\n\n/** A crawl's progress and page results (GET /api/v1/extract/crawl/{id}). Free. */\nexport function scavioCrawlStatus(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read a crawl's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, stopped_reason, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the crawl finishes. Free: reading a job costs 0 credits.\",\n inputSchema: jobStatusSchema,\n execute: async ({ id, limit, ...q }) =>\n (await c.extract.crawlStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })) as unknown as Record<string, unknown>,\n });\n}\n\n/** Extract a list of URLs in one job (/api/v1/extract/batch), then wait (bounded). */\nexport function scavioBatchExtract(config?: ScavioToolConfig) {\n const c = client(config);\n const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;\n return tool({\n description:\n \"Extract a list of URLs (up to 1,000, plan-limited) in one job via the Scavio API, each returned as Markdown, text or HTML exactly like scavio_extract. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_batch_status with the id later. \" +\n JOB_PRICE,\n inputSchema: z.object({\n urls: z.array(z.string()).min(1).max(1000).describe(\"The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000.\"),\n ...jobFields,\n }),\n execute: async (input) => {\n const { wait_seconds, limit, include_content, ...body } = input;\n return startAndWait(\n () => c.extract.batch(body as Parameters<typeof c.extract.batch>[0]),\n (id, q) => c.extract.batchStatus(id, q),\n { wait_seconds, limit, include_content },\n pollMs,\n );\n },\n });\n}\n\n/** A batch's progress and page results (GET /api/v1/extract/batch/{id}). Free. */\nexport function scavioBatchStatus(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read a batch extract's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the batch finishes. Free: reading a job costs 0 credits.\",\n inputSchema: jobStatusSchema,\n execute: async ({ id, limit, ...q }) =>\n (await c.extract.batchStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })) as unknown as Record<string, unknown>,\n });\n}\n\n/**\n * All Scavio tools as an object keyed by tool name, ready to spread into the\n * `tools` option of `generateText` / `streamText`.\n */\nexport function scavioTools(config?: ScavioToolConfig) {\n return {\n scavio_extract: scavioExtract(config),\n scavio_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_youtube_video: scavioYoutubeVideo(config),\n scavio_youtube_transcript: scavioYoutubeTranscript(config),\n scavio_youtube_comments: scavioYoutubeComments(config),\n scavio_youtube_channel: scavioYoutubeChannel(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(config),\n scavio_amazon_offers: scavioAmazonOffers(config),\n scavio_walmart_search: scavioWalmartSearch(config),\n scavio_tiktok_search: scavioTiktokSearch(config),\n scavio_instagram_search: scavioInstagramSearch(config),\n ...(config?.enableCrawl\n ? {\n scavio_map_website: scavioMapWebsite(config),\n scavio_crawl_website: scavioCrawlWebsite(config),\n scavio_crawl_status: scavioCrawlStatus(config),\n scavio_batch_extract: scavioBatchExtract(config),\n scavio_batch_status: scavioBatchStatus(config),\n }\n : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -8,6 +8,14 @@ interface ScavioToolConfig extends ScavioConfig {
|
|
|
8
8
|
* Ignored by `scavioExtract`, which returns page content rather than a list.
|
|
9
9
|
*/
|
|
10
10
|
maxResults?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Add the five website tools (map, crawl, crawl status, batch extract, batch
|
|
13
|
+
* status) to `scavioTools()`. Off by default: a crawl bills per page. The
|
|
14
|
+
* individual factories (`scavioCrawlWebsite` and friends) work regardless.
|
|
15
|
+
*/
|
|
16
|
+
enableCrawl?: boolean;
|
|
17
|
+
/** Milliseconds between progress polls while a crawl or batch tool waits. Default 3000. */
|
|
18
|
+
pollIntervalMs?: number;
|
|
11
19
|
}
|
|
12
20
|
/**
|
|
13
21
|
* Read any URL (/api/v1/extract).
|
|
@@ -47,7 +55,7 @@ declare function scavioYoutubeSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
|
47
55
|
declare function scavioYoutubeVideo(config?: ScavioToolConfig): ai.Tool<{
|
|
48
56
|
video_id: string;
|
|
49
57
|
}, Record<string, unknown>>;
|
|
50
|
-
/** YouTube video transcript / subtitles (
|
|
58
|
+
/** YouTube video transcript / subtitles (5 credits). */
|
|
51
59
|
declare function scavioYoutubeTranscript(config?: ScavioToolConfig): ai.Tool<{
|
|
52
60
|
video_id: string;
|
|
53
61
|
format?: "text" | "srt" | undefined;
|
|
@@ -104,11 +112,112 @@ declare function scavioTiktokSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
|
104
112
|
declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
105
113
|
keyword: string;
|
|
106
114
|
}, Record<string, unknown>>;
|
|
115
|
+
/** Map a website's URLs (/api/v1/extract/map). 1 credit on 'normal'. */
|
|
116
|
+
declare function scavioMapWebsite(config?: ScavioToolConfig): ai.Tool<{
|
|
117
|
+
url: string;
|
|
118
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
119
|
+
limit?: number | undefined;
|
|
120
|
+
search?: string | undefined;
|
|
121
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
122
|
+
include_subdomains?: boolean | undefined;
|
|
123
|
+
include_paths?: string[] | undefined;
|
|
124
|
+
exclude_paths?: string[] | undefined;
|
|
125
|
+
ignore_query_parameters?: boolean | undefined;
|
|
126
|
+
}, Record<string, unknown>>;
|
|
127
|
+
/** Crawl a website (/api/v1/extract/crawl), then wait (bounded) for it. */
|
|
128
|
+
declare function scavioCrawlWebsite(config?: ScavioToolConfig): ai.Tool<{
|
|
129
|
+
url: string;
|
|
130
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
131
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
132
|
+
limit?: number | undefined;
|
|
133
|
+
include_content?: boolean | undefined;
|
|
134
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
135
|
+
include_paths?: string[] | undefined;
|
|
136
|
+
exclude_paths?: string[] | undefined;
|
|
137
|
+
ignore_query_parameters?: boolean | undefined;
|
|
138
|
+
max_pages?: number | undefined;
|
|
139
|
+
max_depth?: number | undefined;
|
|
140
|
+
allow_subdomains?: boolean | undefined;
|
|
141
|
+
wait_seconds?: number | undefined;
|
|
142
|
+
}, Record<string, unknown>>;
|
|
143
|
+
/** A crawl's progress and page results (GET /api/v1/extract/crawl/{id}). Free. */
|
|
144
|
+
declare function scavioCrawlStatus(config?: ScavioToolConfig): ai.Tool<{
|
|
145
|
+
id: string;
|
|
146
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
147
|
+
cursor?: string | undefined;
|
|
148
|
+
limit?: number | undefined;
|
|
149
|
+
include_content?: boolean | undefined;
|
|
150
|
+
}, Record<string, unknown>>;
|
|
151
|
+
/** Extract a list of URLs in one job (/api/v1/extract/batch), then wait (bounded). */
|
|
152
|
+
declare function scavioBatchExtract(config?: ScavioToolConfig): ai.Tool<{
|
|
153
|
+
urls: string[];
|
|
154
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
155
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
156
|
+
limit?: number | undefined;
|
|
157
|
+
include_content?: boolean | undefined;
|
|
158
|
+
wait_seconds?: number | undefined;
|
|
159
|
+
}, Record<string, unknown>>;
|
|
160
|
+
/** A batch's progress and page results (GET /api/v1/extract/batch/{id}). Free. */
|
|
161
|
+
declare function scavioBatchStatus(config?: ScavioToolConfig): ai.Tool<{
|
|
162
|
+
id: string;
|
|
163
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
164
|
+
cursor?: string | undefined;
|
|
165
|
+
limit?: number | undefined;
|
|
166
|
+
include_content?: boolean | undefined;
|
|
167
|
+
}, Record<string, unknown>>;
|
|
107
168
|
/**
|
|
108
169
|
* All Scavio tools as an object keyed by tool name, ready to spread into the
|
|
109
170
|
* `tools` option of `generateText` / `streamText`.
|
|
110
171
|
*/
|
|
111
172
|
declare function scavioTools(config?: ScavioToolConfig): {
|
|
173
|
+
scavio_map_website?: ai.Tool<{
|
|
174
|
+
url: string;
|
|
175
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
176
|
+
limit?: number | undefined;
|
|
177
|
+
search?: string | undefined;
|
|
178
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
179
|
+
include_subdomains?: boolean | undefined;
|
|
180
|
+
include_paths?: string[] | undefined;
|
|
181
|
+
exclude_paths?: string[] | undefined;
|
|
182
|
+
ignore_query_parameters?: boolean | undefined;
|
|
183
|
+
}, Record<string, unknown>> | undefined;
|
|
184
|
+
scavio_crawl_website?: ai.Tool<{
|
|
185
|
+
url: string;
|
|
186
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
187
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
188
|
+
limit?: number | undefined;
|
|
189
|
+
include_content?: boolean | undefined;
|
|
190
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
191
|
+
include_paths?: string[] | undefined;
|
|
192
|
+
exclude_paths?: string[] | undefined;
|
|
193
|
+
ignore_query_parameters?: boolean | undefined;
|
|
194
|
+
max_pages?: number | undefined;
|
|
195
|
+
max_depth?: number | undefined;
|
|
196
|
+
allow_subdomains?: boolean | undefined;
|
|
197
|
+
wait_seconds?: number | undefined;
|
|
198
|
+
}, Record<string, unknown>> | undefined;
|
|
199
|
+
scavio_crawl_status?: ai.Tool<{
|
|
200
|
+
id: string;
|
|
201
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
202
|
+
cursor?: string | undefined;
|
|
203
|
+
limit?: number | undefined;
|
|
204
|
+
include_content?: boolean | undefined;
|
|
205
|
+
}, Record<string, unknown>> | undefined;
|
|
206
|
+
scavio_batch_extract?: ai.Tool<{
|
|
207
|
+
urls: string[];
|
|
208
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
209
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
210
|
+
limit?: number | undefined;
|
|
211
|
+
include_content?: boolean | undefined;
|
|
212
|
+
wait_seconds?: number | undefined;
|
|
213
|
+
}, Record<string, unknown>> | undefined;
|
|
214
|
+
scavio_batch_status?: ai.Tool<{
|
|
215
|
+
id: string;
|
|
216
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
217
|
+
cursor?: string | undefined;
|
|
218
|
+
limit?: number | undefined;
|
|
219
|
+
include_content?: boolean | undefined;
|
|
220
|
+
}, Record<string, unknown>> | undefined;
|
|
112
221
|
scavio_extract: ai.Tool<{
|
|
113
222
|
url: string;
|
|
114
223
|
format?: "html" | "markdown" | "text" | undefined;
|
|
@@ -170,4 +279,4 @@ declare function scavioTools(config?: ScavioToolConfig): {
|
|
|
170
279
|
}, Record<string, unknown>>;
|
|
171
280
|
};
|
|
172
281
|
|
|
173
|
-
export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioExtract, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
|
|
282
|
+
export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioBatchExtract, scavioBatchStatus, scavioCrawlStatus, scavioCrawlWebsite, scavioExtract, scavioInstagramSearch, scavioMapWebsite, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,14 @@ interface ScavioToolConfig extends ScavioConfig {
|
|
|
8
8
|
* Ignored by `scavioExtract`, which returns page content rather than a list.
|
|
9
9
|
*/
|
|
10
10
|
maxResults?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Add the five website tools (map, crawl, crawl status, batch extract, batch
|
|
13
|
+
* status) to `scavioTools()`. Off by default: a crawl bills per page. The
|
|
14
|
+
* individual factories (`scavioCrawlWebsite` and friends) work regardless.
|
|
15
|
+
*/
|
|
16
|
+
enableCrawl?: boolean;
|
|
17
|
+
/** Milliseconds between progress polls while a crawl or batch tool waits. Default 3000. */
|
|
18
|
+
pollIntervalMs?: number;
|
|
11
19
|
}
|
|
12
20
|
/**
|
|
13
21
|
* Read any URL (/api/v1/extract).
|
|
@@ -47,7 +55,7 @@ declare function scavioYoutubeSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
|
47
55
|
declare function scavioYoutubeVideo(config?: ScavioToolConfig): ai.Tool<{
|
|
48
56
|
video_id: string;
|
|
49
57
|
}, Record<string, unknown>>;
|
|
50
|
-
/** YouTube video transcript / subtitles (
|
|
58
|
+
/** YouTube video transcript / subtitles (5 credits). */
|
|
51
59
|
declare function scavioYoutubeTranscript(config?: ScavioToolConfig): ai.Tool<{
|
|
52
60
|
video_id: string;
|
|
53
61
|
format?: "text" | "srt" | undefined;
|
|
@@ -104,11 +112,112 @@ declare function scavioTiktokSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
|
104
112
|
declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
|
|
105
113
|
keyword: string;
|
|
106
114
|
}, Record<string, unknown>>;
|
|
115
|
+
/** Map a website's URLs (/api/v1/extract/map). 1 credit on 'normal'. */
|
|
116
|
+
declare function scavioMapWebsite(config?: ScavioToolConfig): ai.Tool<{
|
|
117
|
+
url: string;
|
|
118
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
119
|
+
limit?: number | undefined;
|
|
120
|
+
search?: string | undefined;
|
|
121
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
122
|
+
include_subdomains?: boolean | undefined;
|
|
123
|
+
include_paths?: string[] | undefined;
|
|
124
|
+
exclude_paths?: string[] | undefined;
|
|
125
|
+
ignore_query_parameters?: boolean | undefined;
|
|
126
|
+
}, Record<string, unknown>>;
|
|
127
|
+
/** Crawl a website (/api/v1/extract/crawl), then wait (bounded) for it. */
|
|
128
|
+
declare function scavioCrawlWebsite(config?: ScavioToolConfig): ai.Tool<{
|
|
129
|
+
url: string;
|
|
130
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
131
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
132
|
+
limit?: number | undefined;
|
|
133
|
+
include_content?: boolean | undefined;
|
|
134
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
135
|
+
include_paths?: string[] | undefined;
|
|
136
|
+
exclude_paths?: string[] | undefined;
|
|
137
|
+
ignore_query_parameters?: boolean | undefined;
|
|
138
|
+
max_pages?: number | undefined;
|
|
139
|
+
max_depth?: number | undefined;
|
|
140
|
+
allow_subdomains?: boolean | undefined;
|
|
141
|
+
wait_seconds?: number | undefined;
|
|
142
|
+
}, Record<string, unknown>>;
|
|
143
|
+
/** A crawl's progress and page results (GET /api/v1/extract/crawl/{id}). Free. */
|
|
144
|
+
declare function scavioCrawlStatus(config?: ScavioToolConfig): ai.Tool<{
|
|
145
|
+
id: string;
|
|
146
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
147
|
+
cursor?: string | undefined;
|
|
148
|
+
limit?: number | undefined;
|
|
149
|
+
include_content?: boolean | undefined;
|
|
150
|
+
}, Record<string, unknown>>;
|
|
151
|
+
/** Extract a list of URLs in one job (/api/v1/extract/batch), then wait (bounded). */
|
|
152
|
+
declare function scavioBatchExtract(config?: ScavioToolConfig): ai.Tool<{
|
|
153
|
+
urls: string[];
|
|
154
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
155
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
156
|
+
limit?: number | undefined;
|
|
157
|
+
include_content?: boolean | undefined;
|
|
158
|
+
wait_seconds?: number | undefined;
|
|
159
|
+
}, Record<string, unknown>>;
|
|
160
|
+
/** A batch's progress and page results (GET /api/v1/extract/batch/{id}). Free. */
|
|
161
|
+
declare function scavioBatchStatus(config?: ScavioToolConfig): ai.Tool<{
|
|
162
|
+
id: string;
|
|
163
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
164
|
+
cursor?: string | undefined;
|
|
165
|
+
limit?: number | undefined;
|
|
166
|
+
include_content?: boolean | undefined;
|
|
167
|
+
}, Record<string, unknown>>;
|
|
107
168
|
/**
|
|
108
169
|
* All Scavio tools as an object keyed by tool name, ready to spread into the
|
|
109
170
|
* `tools` option of `generateText` / `streamText`.
|
|
110
171
|
*/
|
|
111
172
|
declare function scavioTools(config?: ScavioToolConfig): {
|
|
173
|
+
scavio_map_website?: ai.Tool<{
|
|
174
|
+
url: string;
|
|
175
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
176
|
+
limit?: number | undefined;
|
|
177
|
+
search?: string | undefined;
|
|
178
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
179
|
+
include_subdomains?: boolean | undefined;
|
|
180
|
+
include_paths?: string[] | undefined;
|
|
181
|
+
exclude_paths?: string[] | undefined;
|
|
182
|
+
ignore_query_parameters?: boolean | undefined;
|
|
183
|
+
}, Record<string, unknown>> | undefined;
|
|
184
|
+
scavio_crawl_website?: ai.Tool<{
|
|
185
|
+
url: string;
|
|
186
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
187
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
188
|
+
limit?: number | undefined;
|
|
189
|
+
include_content?: boolean | undefined;
|
|
190
|
+
sitemap?: "include" | "only" | "skip" | undefined;
|
|
191
|
+
include_paths?: string[] | undefined;
|
|
192
|
+
exclude_paths?: string[] | undefined;
|
|
193
|
+
ignore_query_parameters?: boolean | undefined;
|
|
194
|
+
max_pages?: number | undefined;
|
|
195
|
+
max_depth?: number | undefined;
|
|
196
|
+
allow_subdomains?: boolean | undefined;
|
|
197
|
+
wait_seconds?: number | undefined;
|
|
198
|
+
}, Record<string, unknown>> | undefined;
|
|
199
|
+
scavio_crawl_status?: ai.Tool<{
|
|
200
|
+
id: string;
|
|
201
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
202
|
+
cursor?: string | undefined;
|
|
203
|
+
limit?: number | undefined;
|
|
204
|
+
include_content?: boolean | undefined;
|
|
205
|
+
}, Record<string, unknown>> | undefined;
|
|
206
|
+
scavio_batch_extract?: ai.Tool<{
|
|
207
|
+
urls: string[];
|
|
208
|
+
format?: "html" | "markdown" | "text" | undefined;
|
|
209
|
+
mode?: "normal" | "advanced" | "ultra" | undefined;
|
|
210
|
+
limit?: number | undefined;
|
|
211
|
+
include_content?: boolean | undefined;
|
|
212
|
+
wait_seconds?: number | undefined;
|
|
213
|
+
}, Record<string, unknown>> | undefined;
|
|
214
|
+
scavio_batch_status?: ai.Tool<{
|
|
215
|
+
id: string;
|
|
216
|
+
status?: "failed" | "succeeded" | "skipped" | undefined;
|
|
217
|
+
cursor?: string | undefined;
|
|
218
|
+
limit?: number | undefined;
|
|
219
|
+
include_content?: boolean | undefined;
|
|
220
|
+
}, Record<string, unknown>> | undefined;
|
|
112
221
|
scavio_extract: ai.Tool<{
|
|
113
222
|
url: string;
|
|
114
223
|
format?: "html" | "markdown" | "text" | undefined;
|
|
@@ -170,4 +279,4 @@ declare function scavioTools(config?: ScavioToolConfig): {
|
|
|
170
279
|
}, Record<string, unknown>>;
|
|
171
280
|
};
|
|
172
281
|
|
|
173
|
-
export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioExtract, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
|
|
282
|
+
export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioBatchExtract, scavioBatchStatus, scavioCrawlStatus, scavioCrawlWebsite, scavioExtract, scavioInstagramSearch, scavioMapWebsite, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
|
package/dist/index.js
CHANGED
|
@@ -33,7 +33,7 @@ function scavioExtract(config) {
|
|
|
33
33
|
"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page."
|
|
34
34
|
),
|
|
35
35
|
mode: z.enum(["normal", "advanced", "ultra"]).optional().describe(
|
|
36
|
-
"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders
|
|
36
|
+
"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders JavaScript-built pages and costs 1, 'ultra' reaches the hardest pages and costs 2. Start on 'normal'."
|
|
37
37
|
)
|
|
38
38
|
}),
|
|
39
39
|
execute: async ({ url, format, mode }) => c.extract({ url, format, mode })
|
|
@@ -96,7 +96,7 @@ function scavioYoutubeVideo(config) {
|
|
|
96
96
|
function scavioYoutubeTranscript(config) {
|
|
97
97
|
const c = client(config);
|
|
98
98
|
return tool({
|
|
99
|
-
description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (
|
|
99
|
+
description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (5 credits).",
|
|
100
100
|
inputSchema: z.object({
|
|
101
101
|
video_id: z.string().describe("YouTube video id or a full watch URL."),
|
|
102
102
|
language: z.string().optional().describe("Transcript language code (default 'en')."),
|
|
@@ -214,6 +214,130 @@ function scavioInstagramSearch(config) {
|
|
|
214
214
|
execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), "users", max)
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
|
+
var JOB_POLL_INTERVAL_MS = 3e3;
|
|
218
|
+
var JOB_WAIT_DEFAULT_SECONDS = 45;
|
|
219
|
+
var JOB_WAIT_MAX_SECONDS = 300;
|
|
220
|
+
var JOB_RESULTS_DEFAULT_LIMIT = 10;
|
|
221
|
+
var JOB_TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
222
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(() => resolve(), ms));
|
|
223
|
+
async function waitForJob(status, id, waitSeconds, pollMs, query) {
|
|
224
|
+
const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1e3;
|
|
225
|
+
for (; ; ) {
|
|
226
|
+
const remaining = deadline - Date.now();
|
|
227
|
+
if (remaining <= 0) break;
|
|
228
|
+
await sleep(Math.min(pollMs, remaining));
|
|
229
|
+
const probe = await status(id, { limit: 1, include_content: false });
|
|
230
|
+
if (JOB_TERMINAL.has(String(probe?.data?.status))) break;
|
|
231
|
+
}
|
|
232
|
+
return await status(id, query);
|
|
233
|
+
}
|
|
234
|
+
async function startAndWait(start, status, input, pollMs) {
|
|
235
|
+
const created = await start();
|
|
236
|
+
const id = created?.data?.id;
|
|
237
|
+
const wait = input.wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;
|
|
238
|
+
if (!id || wait <= 0) return created;
|
|
239
|
+
const query = { limit: input.limit ?? JOB_RESULTS_DEFAULT_LIMIT };
|
|
240
|
+
if (input.include_content !== void 0) query.include_content = input.include_content;
|
|
241
|
+
return waitForJob(status, id, wait, pollMs, query);
|
|
242
|
+
}
|
|
243
|
+
var MODE_DESCRIPTION = "Fetch tier, and the parameter that sets the price: 'normal' (default) is the standard fetch, 'advanced' renders JavaScript-built pages, 'ultra' reaches the hardest pages.";
|
|
244
|
+
var PATHS_DESCRIPTION = "Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].";
|
|
245
|
+
var JOB_PRICE = "Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.";
|
|
246
|
+
var jobFields = {
|
|
247
|
+
format: z.enum(["html", "markdown", "text"]).optional().describe("Format for each page, as on extract (default 'markdown')."),
|
|
248
|
+
mode: z.enum(["normal", "advanced", "ultra"]).optional().describe(MODE_DESCRIPTION),
|
|
249
|
+
wait_seconds: z.number().int().min(0).max(JOB_WAIT_MAX_SECONDS).optional().describe("Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool."),
|
|
250
|
+
limit: z.number().int().min(1).max(100).optional().describe("Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor."),
|
|
251
|
+
include_content: z.boolean().optional().describe("Set false to list results without their page content (default true).")
|
|
252
|
+
};
|
|
253
|
+
var jobStatusSchema = z.object({
|
|
254
|
+
id: z.string().describe("Job id returned when the job was started (data.id)."),
|
|
255
|
+
cursor: z.string().optional().describe("next_cursor from the previous response, to read the next page."),
|
|
256
|
+
limit: jobFields.limit,
|
|
257
|
+
status: z.enum(["succeeded", "failed", "skipped"]).optional().describe("Only results with this status."),
|
|
258
|
+
include_content: jobFields.include_content
|
|
259
|
+
});
|
|
260
|
+
function scavioMapWebsite(config) {
|
|
261
|
+
const c = client(config);
|
|
262
|
+
return tool({
|
|
263
|
+
description: "List a website's page URLs via the Scavio API, gathered from its sitemaps and its start page, deduplicated, filtered by path or search words and limited: `data.links` [{ url, source, lastmod }], `data.total_found`, `data.truncated`. Pages the site's robots.txt disallows are left out. Use it to find the right pages before extracting or crawling. Costs 1 credit on 'normal'; up to 2 on 'advanced' and up to 10 on 'ultra', priced by what the call needed.",
|
|
264
|
+
inputSchema: z.object({
|
|
265
|
+
url: z.string().describe("The site to map. A bare host is upgraded to https."),
|
|
266
|
+
search: z.string().optional().describe("Only return URLs containing every word of this text (case-insensitive)."),
|
|
267
|
+
limit: z.number().int().min(1).max(5e3).optional().describe("Maximum links to return, 1-5000. Default 1000 (or the plan's limit if lower: Free 500, PAYG 1,000, paid plans 5,000)."),
|
|
268
|
+
sitemap: z.enum(["include", "only", "skip"]).optional().describe("'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone."),
|
|
269
|
+
include_subdomains: z.boolean().optional().describe("Also return URLs on subdomains of the site (default false)."),
|
|
270
|
+
include_paths: z.array(z.string()).optional().describe("Keep only URLs matching these. " + PATHS_DESCRIPTION),
|
|
271
|
+
exclude_paths: z.array(z.string()).optional().describe("Drop URLs matching these. " + PATHS_DESCRIPTION),
|
|
272
|
+
ignore_query_parameters: z.boolean().optional().describe("Treat URLs that differ only by query string as one URL (default true)."),
|
|
273
|
+
mode: jobFields.mode
|
|
274
|
+
}),
|
|
275
|
+
execute: async (input) => await c.extract.map(input)
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
function scavioCrawlWebsite(config) {
|
|
279
|
+
const c = client(config);
|
|
280
|
+
const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;
|
|
281
|
+
return tool({
|
|
282
|
+
description: "Crawl a website from one start URL via the Scavio API: same-site pages are discovered and extracted breadth-first within the page, depth and path limits, each returned as Markdown, text or HTML. Pages the site's robots.txt disallows are skipped. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_crawl_status with the id later. " + JOB_PRICE,
|
|
283
|
+
inputSchema: z.object({
|
|
284
|
+
url: z.string().describe("Where the crawl starts. Only pages on the same site are crawled."),
|
|
285
|
+
max_pages: z.number().int().min(1).max(1e4).optional().describe("Maximum pages to fetch. Default 100. Plan limits: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000."),
|
|
286
|
+
max_depth: z.number().int().min(0).max(10).optional().describe("How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page."),
|
|
287
|
+
include_paths: z.array(z.string()).optional().describe("Crawl only paths matching these. " + PATHS_DESCRIPTION),
|
|
288
|
+
exclude_paths: z.array(z.string()).optional().describe("Skip paths matching these. " + PATHS_DESCRIPTION),
|
|
289
|
+
allow_subdomains: z.boolean().optional().describe("Also crawl subdomains of the site (default false)."),
|
|
290
|
+
ignore_query_parameters: z.boolean().optional().describe("Treat URLs that differ only by query string as one page (default true)."),
|
|
291
|
+
sitemap: z.enum(["include", "skip", "only"]).optional().describe("'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links."),
|
|
292
|
+
...jobFields
|
|
293
|
+
}),
|
|
294
|
+
execute: async (input) => {
|
|
295
|
+
const { wait_seconds, limit, include_content, ...body } = input;
|
|
296
|
+
return startAndWait(
|
|
297
|
+
() => c.extract.crawl(body),
|
|
298
|
+
(id, q) => c.extract.crawlStatus(id, q),
|
|
299
|
+
{ wait_seconds, limit, include_content },
|
|
300
|
+
pollMs
|
|
301
|
+
);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
function scavioCrawlStatus(config) {
|
|
306
|
+
const c = client(config);
|
|
307
|
+
return tool({
|
|
308
|
+
description: "Read a crawl's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, stopped_reason, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the crawl finishes. Free: reading a job costs 0 credits.",
|
|
309
|
+
inputSchema: jobStatusSchema,
|
|
310
|
+
execute: async ({ id, limit, ...q }) => await c.extract.crawlStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
function scavioBatchExtract(config) {
|
|
314
|
+
const c = client(config);
|
|
315
|
+
const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;
|
|
316
|
+
return tool({
|
|
317
|
+
description: "Extract a list of URLs (up to 1,000, plan-limited) in one job via the Scavio API, each returned as Markdown, text or HTML exactly like scavio_extract. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_batch_status with the id later. " + JOB_PRICE,
|
|
318
|
+
inputSchema: z.object({
|
|
319
|
+
urls: z.array(z.string()).min(1).max(1e3).describe("The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000."),
|
|
320
|
+
...jobFields
|
|
321
|
+
}),
|
|
322
|
+
execute: async (input) => {
|
|
323
|
+
const { wait_seconds, limit, include_content, ...body } = input;
|
|
324
|
+
return startAndWait(
|
|
325
|
+
() => c.extract.batch(body),
|
|
326
|
+
(id, q) => c.extract.batchStatus(id, q),
|
|
327
|
+
{ wait_seconds, limit, include_content },
|
|
328
|
+
pollMs
|
|
329
|
+
);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
function scavioBatchStatus(config) {
|
|
334
|
+
const c = client(config);
|
|
335
|
+
return tool({
|
|
336
|
+
description: "Read a batch extract's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the batch finishes. Free: reading a job costs 0 credits.",
|
|
337
|
+
inputSchema: jobStatusSchema,
|
|
338
|
+
execute: async ({ id, limit, ...q }) => await c.extract.batchStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })
|
|
339
|
+
});
|
|
340
|
+
}
|
|
217
341
|
function scavioTools(config) {
|
|
218
342
|
return {
|
|
219
343
|
scavio_extract: scavioExtract(config),
|
|
@@ -228,14 +352,26 @@ function scavioTools(config) {
|
|
|
228
352
|
scavio_amazon_offers: scavioAmazonOffers(config),
|
|
229
353
|
scavio_walmart_search: scavioWalmartSearch(config),
|
|
230
354
|
scavio_tiktok_search: scavioTiktokSearch(config),
|
|
231
|
-
scavio_instagram_search: scavioInstagramSearch(config)
|
|
355
|
+
scavio_instagram_search: scavioInstagramSearch(config),
|
|
356
|
+
...config?.enableCrawl ? {
|
|
357
|
+
scavio_map_website: scavioMapWebsite(config),
|
|
358
|
+
scavio_crawl_website: scavioCrawlWebsite(config),
|
|
359
|
+
scavio_crawl_status: scavioCrawlStatus(config),
|
|
360
|
+
scavio_batch_extract: scavioBatchExtract(config),
|
|
361
|
+
scavio_batch_status: scavioBatchStatus(config)
|
|
362
|
+
} : {}
|
|
232
363
|
};
|
|
233
364
|
}
|
|
234
365
|
export {
|
|
235
366
|
scavioAmazonOffers,
|
|
236
367
|
scavioAmazonSearch,
|
|
368
|
+
scavioBatchExtract,
|
|
369
|
+
scavioBatchStatus,
|
|
370
|
+
scavioCrawlStatus,
|
|
371
|
+
scavioCrawlWebsite,
|
|
237
372
|
scavioExtract,
|
|
238
373
|
scavioInstagramSearch,
|
|
374
|
+
scavioMapWebsite,
|
|
239
375
|
scavioRedditSearch,
|
|
240
376
|
scavioSearch,
|
|
241
377
|
scavioTiktokSearch,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { Scavio, type ScavioConfig, type GoogleSearchOptions } from \"scavio\";\n\nexport interface ScavioToolConfig extends ScavioConfig {\n /**\n * Max number of items to keep in the tool's result list. Defaults to 10.\n * Trimmed inside `data` on every platform except Google, whose body is flat.\n * Ignored by `scavioExtract`, which returns page content rather than a list.\n */\n maxResults?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\n/**\n * Google is the ONLY family with a flat body: `organic_results` and friends sit\n * at the top level, next to `response_time` / `credits_used` / `credits_remaining`.\n */\nfunction trimFlat(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const list = res[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, [key]: list.slice(0, max) };\n }\n return res;\n}\n\n/**\n * Every non-Google endpoint nests its payload under `data` - the response is\n * `{ data: { products: [...] }, response_time, credits_used, credits_remaining }`.\n * Trimming the top level is therefore a silent no-op, so those tools trim\n * inside `data`.\n */\nfunction trimData(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const data = res.data;\n if (!data || typeof data !== \"object\") return res;\n const list = (data as Record<string, unknown>)[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, data: { ...(data as Record<string, unknown>), [key]: list.slice(0, max) } };\n }\n return res;\n}\n\n/**\n * Read any URL (/api/v1/extract).\n *\n * The one tool here that is not tied to a platform, and the only one `maxResults`\n * does not touch: extract returns page CONTENT, not a result list, so there is\n * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL\n * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.\n *\n * Credits are a function of `mode`, not a per-call constant: \"normal\" 1,\n * \"advanced\" 1, \"ultra\" 2. Only a successful read is billed.\n */\nexport function scavioExtract(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read any web page via the Scavio API and get it back as clean Markdown (default), plain text, or raw HTML. Use it on any URL, including one returned by the search tools. Returns `data.content` alongside `data.url`, `data.format`, `data.mode` and `data.content_length`. Cost depends on `mode`: 1 credit on 'normal' and 'advanced', 2 on 'ultra'; a dead link, bot wall or timeout is not billed.\",\n inputSchema: z.object({\n url: z\n .string()\n .describe(\n \"The page to read (1-2048 characters). http(s) only; a bare host is upgraded to https, and loopback, private, link-local and metadata hosts are rejected.\",\n ),\n format: z\n .enum([\"html\", \"markdown\", \"text\"])\n .optional()\n .describe(\n \"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page.\",\n ),\n mode: z\n .enum([\"normal\", \"advanced\", \"ultra\"])\n .optional()\n .describe(\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders the page in a browser for JS-built sites and costs 1, 'ultra' routes through residential proxies for the hardest bot walls and costs 2. Start on 'normal'.\",\n ),\n }),\n execute: async ({ url, format, mode }) => c.extract({ url, format, mode }),\n });\n}\n\n/** Google web search (/api/v2/google, 1 credit). */\nexport function scavioSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search the web with Google via the Scavio API (1 credit). Returns real-time organic search results, each with a title, link, and snippet, under `organic_results`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n countryCode: z.string().optional().describe('Two-letter country code to localize results, e.g. \"us\".'),\n language: z.string().optional().describe('Two-letter UI language code, e.g. \"en\".'),\n page: z.number().int().optional().describe(\"1-based result page; page 2 starts at result 10.\"),\n device: z.enum([\"desktop\", \"mobile\"]).optional().describe(\"Device to emulate.\"),\n nfpr: z.boolean().optional().describe(\"Disable spelling auto-correction / similar-result substitution when true.\"),\n }),\n execute: async ({ query, countryCode, language, page, device, nfpr }) => {\n const params: GoogleSearchOptions = { query };\n if (countryCode) params.gl = countryCode;\n if (language) params.hl = language;\n if (page && page > 1) params.start = (page - 1) * 10;\n if (device) params.device = device;\n if (nfpr !== undefined) params.nfpr = nfpr;\n return trimFlat(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search (2 credits). */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search YouTube for videos, channels, or playlists via the Scavio API (2 credits). Videos come back under `data.results`, with `data.channels` and `data.playlists` alongside.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n upload_date: z.string().optional().describe(\"Upload date filter, e.g. 'today', 'this_week', 'this_month'.\"),\n type: z.string().optional().describe(\"Result type: 'video', 'channel', 'playlist', 'movie'.\"),\n duration: z.string().optional().describe(\"Duration filter: 'short', 'medium', 'long'.\"),\n sort_by: z.string().optional().describe(\"Sort order: 'relevance', 'date', 'view_count', 'rating'.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, upload_date, type, duration, sort_by, cursor }) =>\n trimData(\n await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor } as Parameters<\n typeof c.youtube.search\n >[0]),\n \"results\",\n max,\n ),\n });\n}\n\n/** YouTube video details (1 credit). */\nexport function scavioYoutubeVideo(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n }),\n execute: async ({ video_id }) => c.youtube.video({ video_id }),\n });\n}\n\n/** YouTube video transcript / subtitles (8 credits). */\nexport function scavioYoutubeTranscript(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube video's transcript or timed subtitles via the Scavio API (8 credits).\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n language: z.string().optional().describe(\"Transcript language code (default 'en').\"),\n format: z.enum([\"text\", \"srt\"]).optional().describe(\"'text' for a plain transcript, 'srt' for timed subtitles.\"),\n }),\n execute: async ({ video_id, language, format }) =>\n c.youtube.transcript({ video_id, language, format } as Parameters<typeof c.youtube.transcript>[0]),\n });\n}\n\n/** YouTube video comments (1 credit). */\nexport function scavioYoutubeComments(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"List comments on a YouTube video via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n cursor: z.string().optional().describe(\"Pagination cursor.\"),\n }),\n execute: async ({ video_id, cursor }) =>\n trimData(\n await c.youtube.comments({ video_id, cursor } as Parameters<typeof c.youtube.comments>[0]),\n \"comments\",\n max,\n ),\n });\n}\n\n/** YouTube channel details (1 credit). */\nexport function scavioYoutubeChannel(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.\",\n inputSchema: z.object({\n channel_id: z.string().describe(\"YouTube channel id, @handle, or channel URL.\"),\n }),\n execute: async ({ channel_id }) => c.youtube.channel({ channel_id }),\n });\n}\n\n/**\n * Reddit post search (1 credit).\n *\n * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or\n * filter by type, so no such input is offered. The API silently ignores those\n * params, which would leave a model believing it had filtered when it had not.\n */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Reddit posts via the Scavio API (1 credit). Returns matching posts under `data.results` with `data.next_cursor` for the next page. Results cannot be sorted or filtered by type.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), \"results\", max),\n });\n}\n\n/**\n * Amazon product search.\n *\n * `domain` was dropped in favour of `country`, a two-letter marketplace code -\n * the upstream provider changed in 2026-07 and no longer takes a domain\n * suffix. It still works on the wire as a deprecated alias, but a model should\n * only ever see one spelling of a param.\n */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ query, country }) =>\n trimData(await c.amazon.search({ query, country }), \"products\", max),\n });\n}\n\n/** Every seller offer for one Amazon ASIN. */\nexport function scavioAmazonOffers(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"List every seller offer for one Amazon ASIN via the Scavio API: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only.\",\n inputSchema: z.object({\n asin: z.string().describe(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ asin, country }) =>\n trimData(await c.amazon.offers({ asin, country }), \"offers\", max),\n });\n}\n\n/** Walmart product search. */\nexport function scavioWalmartSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Walmart for products via the Scavio API. Products come back under `data.products`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trimData(await c.walmart.search({ query }), \"products\", max),\n });\n}\n\n/** TikTok video search. */\nexport function scavioTiktokSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.enum([\"0\", \"1\"]).optional().describe(\"Sort order: '0' relevance, '1' most likes.\"),\n publish_time: z\n .enum([\"0\", \"1\", \"7\", \"30\", \"90\", \"180\"])\n .optional()\n .describe(\"Publish window in days: '0' all time, '1', '7', '30', '90', '180'.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trimData(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\n \"aweme_list\",\n max,\n ),\n });\n}\n\n/** Instagram user search. */\nexport function scavioInstagramSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), \"users\", max),\n });\n}\n\n/**\n * All Scavio tools as an object keyed by tool name, ready to spread into the\n * `tools` option of `generateText` / `streamText`.\n */\nexport function scavioTools(config?: ScavioToolConfig) {\n return {\n scavio_extract: scavioExtract(config),\n scavio_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_youtube_video: scavioYoutubeVideo(config),\n scavio_youtube_transcript: scavioYoutubeTranscript(config),\n scavio_youtube_comments: scavioYoutubeComments(config),\n scavio_youtube_channel: scavioYoutubeChannel(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(config),\n scavio_amazon_offers: scavioAmazonOffers(config),\n scavio_walmart_search: scavioWalmartSearch(config),\n scavio_tiktok_search: scavioTiktokSearch(config),\n scavio_instagram_search: scavioInstagramSearch(config),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { tool } from \"ai\";\nimport { z } from \"zod\";\nimport { Scavio, type ScavioConfig, type GoogleSearchOptions } from \"scavio\";\n\nexport interface ScavioToolConfig extends ScavioConfig {\n /**\n * Max number of items to keep in the tool's result list. Defaults to 10.\n * Trimmed inside `data` on every platform except Google, whose body is flat.\n * Ignored by `scavioExtract`, which returns page content rather than a list.\n */\n maxResults?: number;\n /**\n * Add the five website tools (map, crawl, crawl status, batch extract, batch\n * status) to `scavioTools()`. Off by default: a crawl bills per page. The\n * individual factories (`scavioCrawlWebsite` and friends) work regardless.\n */\n enableCrawl?: boolean;\n /** Milliseconds between progress polls while a crawl or batch tool waits. Default 3000. */\n pollIntervalMs?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\n/**\n * Google is the ONLY family with a flat body: `organic_results` and friends sit\n * at the top level, next to `response_time` / `credits_used` / `credits_remaining`.\n */\nfunction trimFlat(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const list = res[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, [key]: list.slice(0, max) };\n }\n return res;\n}\n\n/**\n * Every non-Google endpoint nests its payload under `data` - the response is\n * `{ data: { products: [...] }, response_time, credits_used, credits_remaining }`.\n * Trimming the top level is therefore a silent no-op, so those tools trim\n * inside `data`.\n */\nfunction trimData(res: Record<string, unknown>, key: string, max: number): Record<string, unknown> {\n const data = res.data;\n if (!data || typeof data !== \"object\") return res;\n const list = (data as Record<string, unknown>)[key];\n if (Array.isArray(list) && list.length > max) {\n return { ...res, data: { ...(data as Record<string, unknown>), [key]: list.slice(0, max) } };\n }\n return res;\n}\n\n/**\n * Read any URL (/api/v1/extract).\n *\n * The one tool here that is not tied to a platform, and the only one `maxResults`\n * does not touch: extract returns page CONTENT, not a result list, so there is\n * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL\n * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.\n *\n * Credits are a function of `mode`, not a per-call constant: \"normal\" 1,\n * \"advanced\" 1, \"ultra\" 2. Only a successful read is billed.\n */\nexport function scavioExtract(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read any web page via the Scavio API and get it back as clean Markdown (default), plain text, or raw HTML. Use it on any URL, including one returned by the search tools. Returns `data.content` alongside `data.url`, `data.format`, `data.mode` and `data.content_length`. Cost depends on `mode`: 1 credit on 'normal' and 'advanced', 2 on 'ultra'; a dead link, bot wall or timeout is not billed.\",\n inputSchema: z.object({\n url: z\n .string()\n .describe(\n \"The page to read (1-2048 characters). http(s) only; a bare host is upgraded to https, and loopback, private, link-local and metadata hosts are rejected.\",\n ),\n format: z\n .enum([\"html\", \"markdown\", \"text\"])\n .optional()\n .describe(\n \"Output format (default 'markdown'): 'markdown' is a readability extraction with page chrome stripped, 'text' is that flattened to plain text, 'html' is the raw page.\",\n ),\n mode: z\n .enum([\"normal\", \"advanced\", \"ultra\"])\n .optional()\n .describe(\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is a plain fetch and costs 1 credit, 'advanced' renders JavaScript-built pages and costs 1, 'ultra' reaches the hardest pages and costs 2. Start on 'normal'.\",\n ),\n }),\n execute: async ({ url, format, mode }) => c.extract({ url, format, mode }),\n });\n}\n\n/** Google web search (/api/v2/google, 1 credit). */\nexport function scavioSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search the web with Google via the Scavio API (1 credit). Returns real-time organic search results, each with a title, link, and snippet, under `organic_results`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n countryCode: z.string().optional().describe('Two-letter country code to localize results, e.g. \"us\".'),\n language: z.string().optional().describe('Two-letter UI language code, e.g. \"en\".'),\n page: z.number().int().optional().describe(\"1-based result page; page 2 starts at result 10.\"),\n device: z.enum([\"desktop\", \"mobile\"]).optional().describe(\"Device to emulate.\"),\n nfpr: z.boolean().optional().describe(\"Disable spelling auto-correction / similar-result substitution when true.\"),\n }),\n execute: async ({ query, countryCode, language, page, device, nfpr }) => {\n const params: GoogleSearchOptions = { query };\n if (countryCode) params.gl = countryCode;\n if (language) params.hl = language;\n if (page && page > 1) params.start = (page - 1) * 10;\n if (device) params.device = device;\n if (nfpr !== undefined) params.nfpr = nfpr;\n return trimFlat(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search (2 credits). */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search YouTube for videos, channels, or playlists via the Scavio API (2 credits). Videos come back under `data.results`, with `data.channels` and `data.playlists` alongside.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n upload_date: z.string().optional().describe(\"Upload date filter, e.g. 'today', 'this_week', 'this_month'.\"),\n type: z.string().optional().describe(\"Result type: 'video', 'channel', 'playlist', 'movie'.\"),\n duration: z.string().optional().describe(\"Duration filter: 'short', 'medium', 'long'.\"),\n sort_by: z.string().optional().describe(\"Sort order: 'relevance', 'date', 'view_count', 'rating'.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, upload_date, type, duration, sort_by, cursor }) =>\n trimData(\n await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor } as Parameters<\n typeof c.youtube.search\n >[0]),\n \"results\",\n max,\n ),\n });\n}\n\n/** YouTube video details (1 credit). */\nexport function scavioYoutubeVideo(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n }),\n execute: async ({ video_id }) => c.youtube.video({ video_id }),\n });\n}\n\n/** YouTube video transcript / subtitles (5 credits). */\nexport function scavioYoutubeTranscript(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube video's transcript or timed subtitles via the Scavio API (5 credits).\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n language: z.string().optional().describe(\"Transcript language code (default 'en').\"),\n format: z.enum([\"text\", \"srt\"]).optional().describe(\"'text' for a plain transcript, 'srt' for timed subtitles.\"),\n }),\n execute: async ({ video_id, language, format }) =>\n c.youtube.transcript({ video_id, language, format } as Parameters<typeof c.youtube.transcript>[0]),\n });\n}\n\n/** YouTube video comments (1 credit). */\nexport function scavioYoutubeComments(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"List comments on a YouTube video via the Scavio API.\",\n inputSchema: z.object({\n video_id: z.string().describe(\"YouTube video id or a full watch URL.\"),\n cursor: z.string().optional().describe(\"Pagination cursor.\"),\n }),\n execute: async ({ video_id, cursor }) =>\n trimData(\n await c.youtube.comments({ video_id, cursor } as Parameters<typeof c.youtube.comments>[0]),\n \"comments\",\n max,\n ),\n });\n}\n\n/** YouTube channel details (1 credit). */\nexport function scavioYoutubeChannel(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.\",\n inputSchema: z.object({\n channel_id: z.string().describe(\"YouTube channel id, @handle, or channel URL.\"),\n }),\n execute: async ({ channel_id }) => c.youtube.channel({ channel_id }),\n });\n}\n\n/**\n * Reddit post search (1 credit).\n *\n * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or\n * filter by type, so no such input is offered. The API silently ignores those\n * params, which would leave a model believing it had filtered when it had not.\n */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Reddit posts via the Scavio API (1 credit). Returns matching posts under `data.results` with `data.next_cursor` for the next page. Results cannot be sorted or filtered by type.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n cursor: z.string().optional().describe(\"Pagination cursor (`next_cursor`) from a prior response.\"),\n }),\n execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), \"results\", max),\n });\n}\n\n/**\n * Amazon product search.\n *\n * `domain` was dropped in favour of `country`, a two-letter marketplace code -\n * the upstream provider changed in 2026-07 and no longer takes a domain\n * suffix. It still works on the wire as a deprecated alias, but a model should\n * only ever see one spelling of a param.\n */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ query, country }) =>\n trimData(await c.amazon.search({ query, country }), \"products\", max),\n });\n}\n\n/** Every seller offer for one Amazon ASIN. */\nexport function scavioAmazonOffers(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"List every seller offer for one Amazon ASIN via the Scavio API: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only.\",\n inputSchema: z.object({\n asin: z.string().describe(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: z\n .string()\n .optional()\n .describe(\n \"Marketplace country code (ISO 3166-1 alpha-2), not a domain: us (default), gb (the UK is gb, not uk), de, fr, jp, ... An unknown code falls back to us.\"\n ),\n }),\n execute: async ({ asin, country }) =>\n trimData(await c.amazon.offers({ asin, country }), \"offers\", max),\n });\n}\n\n/** Walmart product search. */\nexport function scavioWalmartSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Walmart for products via the Scavio API. Products come back under `data.products`.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trimData(await c.walmart.search({ query }), \"products\", max),\n });\n}\n\n/** TikTok video search. */\nexport function scavioTiktokSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.enum([\"0\", \"1\"]).optional().describe(\"Sort order: '0' relevance, '1' most likes.\"),\n publish_time: z\n .enum([\"0\", \"1\", \"7\", \"30\", \"90\", \"180\"])\n .optional()\n .describe(\"Publish window in days: '0' all time, '1', '7', '30', '90', '180'.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trimData(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\n \"aweme_list\",\n max,\n ),\n });\n}\n\n/** Instagram user search. */\nexport function scavioInstagramSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description:\n \"Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), \"users\", max),\n });\n}\n\n// ---------------------------------------------------------------------------\n// Website map, crawl and batch: the multi-page members of the Extract family.\n//\n// Map answers in one call. Crawl and batch are background jobs: the start tools\n// post the job, then wait up to wait_seconds (default 45, max 300) for it to\n// finish, polling progress without page content, and return the job's status\n// with its first page of results either way. A job still running when the wait\n// ends keeps going server-side; read the rest with the matching status tool.\n// ---------------------------------------------------------------------------\n\nconst JOB_POLL_INTERVAL_MS = 3_000;\nconst JOB_WAIT_DEFAULT_SECONDS = 45;\nconst JOB_WAIT_MAX_SECONDS = 300;\nconst JOB_RESULTS_DEFAULT_LIMIT = 10;\nconst JOB_TERMINAL = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\ntype JobQuery = {\n cursor?: string;\n limit?: number;\n status?: \"succeeded\" | \"failed\" | \"skipped\";\n include_content?: boolean;\n};\ntype JobPayload = { data?: { id?: string; status?: string } } & Record<string, unknown>;\ntype JobStatusFn = (id: string, query: JobQuery) => Promise<unknown>;\n\n// lib is ES2022 only (no DOM or Node types); every runtime this targets has setTimeout.\ndeclare const setTimeout: (callback: () => void, ms: number) => unknown;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(() => resolve(), ms));\n\n/** Poll a job (content-free) until it finishes or the wait runs out, then read one results page. */\nasync function waitForJob(\n status: JobStatusFn,\n id: string,\n waitSeconds: number,\n pollMs: number,\n query: JobQuery,\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1000;\n for (;;) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollMs, remaining));\n const probe = (await status(id, { limit: 1, include_content: false })) as JobPayload;\n if (JOB_TERMINAL.has(String(probe?.data?.status))) break;\n }\n return (await status(id, query)) as Record<string, unknown>;\n}\n\n/** Start a job, then wait for it (bounded). wait_seconds 0 returns the 202 payload. */\nasync function startAndWait(\n start: () => Promise<unknown>,\n status: JobStatusFn,\n input: { wait_seconds?: number; limit?: number; include_content?: boolean },\n pollMs: number,\n): Promise<Record<string, unknown>> {\n const created = (await start()) as JobPayload;\n const id = created?.data?.id;\n const wait = input.wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;\n if (!id || wait <= 0) return created;\n const query: JobQuery = { limit: input.limit ?? JOB_RESULTS_DEFAULT_LIMIT };\n if (input.include_content !== undefined) query.include_content = input.include_content;\n return waitForJob(status, id, wait, pollMs, query);\n}\n\nconst MODE_DESCRIPTION =\n \"Fetch tier, and the parameter that sets the price: 'normal' (default) is the standard fetch, 'advanced' renders JavaScript-built pages, 'ultra' reaches the hardest pages.\";\nconst PATHS_DESCRIPTION =\n \"Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].\";\nconst JOB_PRICE =\n \"Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.\";\n\nconst jobFields = {\n format: z.enum([\"html\", \"markdown\", \"text\"]).optional().describe(\"Format for each page, as on extract (default 'markdown').\"),\n mode: z.enum([\"normal\", \"advanced\", \"ultra\"]).optional().describe(MODE_DESCRIPTION),\n wait_seconds: z\n .number()\n .int()\n .min(0)\n .max(JOB_WAIT_MAX_SECONDS)\n .optional()\n .describe(\"Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool.\"),\n limit: z\n .number()\n .int()\n .min(1)\n .max(100)\n .optional()\n .describe(\"Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor.\"),\n include_content: z.boolean().optional().describe(\"Set false to list results without their page content (default true).\"),\n};\n\nconst jobStatusSchema = z.object({\n id: z.string().describe(\"Job id returned when the job was started (data.id).\"),\n cursor: z.string().optional().describe(\"next_cursor from the previous response, to read the next page.\"),\n limit: jobFields.limit,\n status: z.enum([\"succeeded\", \"failed\", \"skipped\"]).optional().describe(\"Only results with this status.\"),\n include_content: jobFields.include_content,\n});\n\n/** Map a website's URLs (/api/v1/extract/map). 1 credit on 'normal'. */\nexport function scavioMapWebsite(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"List a website's page URLs via the Scavio API, gathered from its sitemaps and its start page, deduplicated, filtered by path or search words and limited: `data.links` [{ url, source, lastmod }], `data.total_found`, `data.truncated`. Pages the site's robots.txt disallows are left out. Use it to find the right pages before extracting or crawling. Costs 1 credit on 'normal'; up to 2 on 'advanced' and up to 10 on 'ultra', priced by what the call needed.\",\n inputSchema: z.object({\n url: z.string().describe(\"The site to map. A bare host is upgraded to https.\"),\n search: z.string().optional().describe(\"Only return URLs containing every word of this text (case-insensitive).\"),\n limit: z.number().int().min(1).max(5000).optional().describe(\"Maximum links to return, 1-5000. Default 1000 (or the plan's limit if lower: Free 500, PAYG 1,000, paid plans 5,000).\"),\n sitemap: z.enum([\"include\", \"only\", \"skip\"]).optional().describe(\"'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone.\"),\n include_subdomains: z.boolean().optional().describe(\"Also return URLs on subdomains of the site (default false).\"),\n include_paths: z.array(z.string()).optional().describe(\"Keep only URLs matching these. \" + PATHS_DESCRIPTION),\n exclude_paths: z.array(z.string()).optional().describe(\"Drop URLs matching these. \" + PATHS_DESCRIPTION),\n ignore_query_parameters: z.boolean().optional().describe(\"Treat URLs that differ only by query string as one URL (default true).\"),\n mode: jobFields.mode,\n }),\n execute: async (input) =>\n (await c.extract.map(input as Parameters<typeof c.extract.map>[0])) as unknown as Record<string, unknown>,\n });\n}\n\n/** Crawl a website (/api/v1/extract/crawl), then wait (bounded) for it. */\nexport function scavioCrawlWebsite(config?: ScavioToolConfig) {\n const c = client(config);\n const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;\n return tool({\n description:\n \"Crawl a website from one start URL via the Scavio API: same-site pages are discovered and extracted breadth-first within the page, depth and path limits, each returned as Markdown, text or HTML. Pages the site's robots.txt disallows are skipped. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_crawl_status with the id later. \" +\n JOB_PRICE,\n inputSchema: z.object({\n url: z.string().describe(\"Where the crawl starts. Only pages on the same site are crawled.\"),\n max_pages: z.number().int().min(1).max(10000).optional().describe(\"Maximum pages to fetch. Default 100. Plan limits: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000.\"),\n max_depth: z.number().int().min(0).max(10).optional().describe(\"How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page.\"),\n include_paths: z.array(z.string()).optional().describe(\"Crawl only paths matching these. \" + PATHS_DESCRIPTION),\n exclude_paths: z.array(z.string()).optional().describe(\"Skip paths matching these. \" + PATHS_DESCRIPTION),\n allow_subdomains: z.boolean().optional().describe(\"Also crawl subdomains of the site (default false).\"),\n ignore_query_parameters: z.boolean().optional().describe(\"Treat URLs that differ only by query string as one page (default true).\"),\n sitemap: z.enum([\"include\", \"skip\", \"only\"]).optional().describe(\"'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links.\"),\n ...jobFields,\n }),\n execute: async (input) => {\n const { wait_seconds, limit, include_content, ...body } = input;\n return startAndWait(\n () => c.extract.crawl(body as Parameters<typeof c.extract.crawl>[0]),\n (id, q) => c.extract.crawlStatus(id, q),\n { wait_seconds, limit, include_content },\n pollMs,\n );\n },\n });\n}\n\n/** A crawl's progress and page results (GET /api/v1/extract/crawl/{id}). Free. */\nexport function scavioCrawlStatus(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read a crawl's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, stopped_reason, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the crawl finishes. Free: reading a job costs 0 credits.\",\n inputSchema: jobStatusSchema,\n execute: async ({ id, limit, ...q }) =>\n (await c.extract.crawlStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })) as unknown as Record<string, unknown>,\n });\n}\n\n/** Extract a list of URLs in one job (/api/v1/extract/batch), then wait (bounded). */\nexport function scavioBatchExtract(config?: ScavioToolConfig) {\n const c = client(config);\n const pollMs = config?.pollIntervalMs ?? JOB_POLL_INTERVAL_MS;\n return tool({\n description:\n \"Extract a list of URLs (up to 1,000, plan-limited) in one job via the Scavio API, each returned as Markdown, text or HTML exactly like scavio_extract. Waits up to wait_seconds (default 45) and returns `data` { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call scavio_batch_status with the id later. \" +\n JOB_PRICE,\n inputSchema: z.object({\n urls: z.array(z.string()).min(1).max(1000).describe(\"The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000.\"),\n ...jobFields,\n }),\n execute: async (input) => {\n const { wait_seconds, limit, include_content, ...body } = input;\n return startAndWait(\n () => c.extract.batch(body as Parameters<typeof c.extract.batch>[0]),\n (id, q) => c.extract.batchStatus(id, q),\n { wait_seconds, limit, include_content },\n pollMs,\n );\n },\n });\n}\n\n/** A batch's progress and page results (GET /api/v1/extract/batch/{id}). Free. */\nexport function scavioBatchStatus(config?: ScavioToolConfig) {\n const c = client(config);\n return tool({\n description:\n \"Read a batch extract's progress and its page results by job id via the Scavio API, paged by cursor: `data` { status, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the batch finishes. Free: reading a job costs 0 credits.\",\n inputSchema: jobStatusSchema,\n execute: async ({ id, limit, ...q }) =>\n (await c.extract.batchStatus(id, { ...q, limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT })) as unknown as Record<string, unknown>,\n });\n}\n\n/**\n * All Scavio tools as an object keyed by tool name, ready to spread into the\n * `tools` option of `generateText` / `streamText`.\n */\nexport function scavioTools(config?: ScavioToolConfig) {\n return {\n scavio_extract: scavioExtract(config),\n scavio_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_youtube_video: scavioYoutubeVideo(config),\n scavio_youtube_transcript: scavioYoutubeTranscript(config),\n scavio_youtube_comments: scavioYoutubeComments(config),\n scavio_youtube_channel: scavioYoutubeChannel(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(config),\n scavio_amazon_offers: scavioAmazonOffers(config),\n scavio_walmart_search: scavioWalmartSearch(config),\n scavio_tiktok_search: scavioTiktokSearch(config),\n scavio_instagram_search: scavioInstagramSearch(config),\n ...(config?.enableCrawl\n ? {\n scavio_map_website: scavioMapWebsite(config),\n scavio_crawl_website: scavioCrawlWebsite(config),\n scavio_crawl_status: scavioCrawlStatus(config),\n scavio_batch_extract: scavioBatchExtract(config),\n scavio_batch_status: scavioBatchStatus(config),\n }\n : {}),\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scavio/ai-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Scavio search
|
|
3
|
+
"version": "0.5.1",
|
|
4
|
+
"description": "Scavio search, URL-extraction and website crawl tools for the Vercel AI SDK (extract any URL, map, crawl and batch-extract sites, plus Google, YouTube, Reddit, Amazon, Walmart, TikTok, Instagram).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"module": "./dist/index.js",
|
|
@@ -33,6 +33,9 @@
|
|
|
33
33
|
"tools",
|
|
34
34
|
"search",
|
|
35
35
|
"extract",
|
|
36
|
+
"web-crawler",
|
|
37
|
+
"website-crawler",
|
|
38
|
+
"sitemap",
|
|
36
39
|
"web-scraping",
|
|
37
40
|
"agents"
|
|
38
41
|
],
|
|
@@ -50,12 +53,12 @@
|
|
|
50
53
|
"zod": ">=3"
|
|
51
54
|
},
|
|
52
55
|
"dependencies": {
|
|
53
|
-
"scavio": "^0.
|
|
56
|
+
"scavio": "^0.23.0"
|
|
54
57
|
},
|
|
55
58
|
"devDependencies": {
|
|
56
59
|
"@ai-sdk/openai": "^3.0.74",
|
|
57
60
|
"ai": "^6.0.208",
|
|
58
|
-
"scavio": "^0.
|
|
61
|
+
"scavio": "^0.23.0",
|
|
59
62
|
"tsup": "^8.0.0",
|
|
60
63
|
"typescript": "^5.4.0",
|
|
61
64
|
"vitest": "^2.0.0",
|