@scavio/ai-sdk 0.2.2 → 0.4.0

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 CHANGED
@@ -1,8 +1,31 @@
1
1
  # @scavio/ai-sdk
2
2
 
3
- Scavio search tools for the [Vercel AI SDK](https://sdk.vercel.ai). Give any AI SDK agent real-time
4
- search across Google, YouTube, Reddit, Amazon, Walmart, TikTok, and Instagram via the
5
- [Scavio](https://scavio.dev) API.
3
+ Scavio search and page-extraction tools for the [Vercel AI SDK](https://sdk.vercel.ai). Give any AI
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.
6
+
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,
10
+ adding X, LinkedIn, TikTok Shop, eBay, Target, Home Depot, Zillow, Redfin,
11
+ Booking, Airbnb, Tripadvisor, Yelp, Indeed, Glassdoor, the App Store, Google
12
+ Play, SEC, Companies House, G2, Capterra, Google Ads, Meta Ad Library, Threads,
13
+ Kuaishou and the Google verticals (Maps, Shopping, News, Flights, Hotels,
14
+ Trends, AI Mode). To reach all of them, point your agent at the
15
+ [Scavio MCP server](https://scavio.dev/docs/mcp-server) at `mcp.scavio.dev` --
16
+ 191 tools over every endpoint, nothing to vendor.
17
+
18
+ Credits are not uniform: most calls cost 1, YouTube search costs 2 and
19
+ transcript costs 8, Instagram costs 2 to 10 depending on the endpoint, and
20
+ `scavio_extract` is priced by the `mode` you ask for (1 / 1 / 2), not per call.
21
+
22
+ > **Amazon changed (breaking).** The upstream provider moved in 2026-07:
23
+ > `domain` is replaced by `country`, a two-letter marketplace code (`us`, `gb`
24
+ > -- the UK is `gb`, not `uk` -- `de`, `jp`, ...), and `sort_by`, `pages`,
25
+ > `category_id`, `merchant_id`, `language`, `currency`, `device`, `zip_code`
26
+ > and `autoselect_variant` are gone. The marketplace ignores all of them
27
+ > (`sort_by` returns the identical unordered set for every value), so they are
28
+ > removed rather than kept as silent no-ops. Rank and filter results yourself.
6
29
 
7
30
  ## Install
8
31
 
@@ -22,7 +45,7 @@ import { scavioSearch, scavioTools } from "@scavio/ai-sdk";
22
45
 
23
46
  // A single tool:
24
47
  const res = await generateText({
25
- model: openai("gpt-4o-mini"),
48
+ model: openai("gpt-5.5"),
26
49
  tools: { scavio_search: scavioSearch({ maxResults: 5 }) },
27
50
  stopWhen: stepCountIs(3),
28
51
  prompt: "Find the official GitHub repo of the Agno framework",
@@ -30,7 +53,7 @@ const res = await generateText({
30
53
 
31
54
  // Or all tools at once:
32
55
  const res2 = await generateText({
33
- model: openai("gpt-4o-mini"),
56
+ model: openai("gpt-5.5"),
34
57
  tools: scavioTools(),
35
58
  stopWhen: stepCountIs(3),
36
59
  prompt: "Compare prices for a mechanical keyboard on Amazon and Walmart",
@@ -41,17 +64,54 @@ const res2 = await generateText({
41
64
 
42
65
  | Factory | Tool name | Provider |
43
66
  | --- | --- | --- |
44
- | `scavioSearch` | `scavio_search` | Google web search |
45
- | `scavioYoutubeSearch` | `scavio_youtube_search` | YouTube video search |
46
- | `scavioRedditSearch` | `scavio_reddit_search` | Reddit (2 credits) |
47
- | `scavioAmazonSearch` | `scavio_amazon_search` | Amazon products |
48
- | `scavioWalmartSearch` | `scavio_walmart_search` | Walmart products |
49
- | `scavioTiktokSearch` | `scavio_tiktok_search` | TikTok videos |
50
- | `scavioInstagramSearch` | `scavio_instagram_search` | Instagram users |
67
+ | `scavioExtract` | `scavio_extract` | Read any URL as Markdown / text / HTML, `/api/v1/extract` (1 credit on `normal` and `advanced`, 2 on `ultra`) |
68
+ | `scavioSearch` | `scavio_search` | Google web search, `/api/v2/google` (1 credit) |
69
+ | `scavioYoutubeSearch` | `scavio_youtube_search` | YouTube video search (2 credits) |
70
+ | `scavioYoutubeVideo` | `scavio_youtube_video` | YouTube video details (1 credit) |
71
+ | `scavioYoutubeTranscript` | `scavio_youtube_transcript` | YouTube transcript / subtitles (8 credits) |
72
+ | `scavioYoutubeComments` | `scavio_youtube_comments` | YouTube video comments (1 credit) |
73
+ | `scavioYoutubeChannel` | `scavio_youtube_channel` | YouTube channel details (1 credit) |
74
+ | `scavioRedditSearch` | `scavio_reddit_search` | Reddit posts (1 credit) |
75
+ | `scavioAmazonSearch` | `scavio_amazon_search` | Amazon products (1 credit) |
76
+ | `scavioAmazonOffers` | `scavio_amazon_offers` | Amazon seller offers for one ASIN (1 credit) |
77
+ | `scavioWalmartSearch` | `scavio_walmart_search` | Walmart products (1 credit) |
78
+ | `scavioTiktokSearch` | `scavio_tiktok_search` | TikTok videos (1 credit) |
79
+ | `scavioInstagramSearch` | `scavio_instagram_search` | Instagram users (10 credits) |
51
80
  | `scavioTools` | all of the above | bundle for `tools:` |
52
81
 
53
82
  Each factory accepts `{ apiKey?, maxResults?, ...ScavioConfig }`. The key falls back to `SCAVIO_API_KEY`.
54
- Get a key at [dashboard.scavio.dev](https://dashboard.scavio.dev).
83
+ Get a key at [dashboard.scavio.dev](https://dashboard.scavio.dev) - new accounts get 50 free credits, no
84
+ credit card.
85
+
86
+ `maxResults` trims the result list in place. Google returns a flat body, so it trims
87
+ `organic_results`; every other endpoint nests its payload under `data`, so those trim inside `data`
88
+ (`data.results`, `data.products`, `data.aweme_list`, `data.users`, ...) and the
89
+ `{ data, response_time, credits_used, credits_remaining }` envelope is preserved. `scavioExtract`
90
+ ignores `maxResults`: it returns page content, not a list, so the page comes back whole.
91
+
92
+ ### Reading a page
93
+
94
+ ```ts
95
+ const page = await generateText({
96
+ model: openai("gpt-5.5"),
97
+ tools: { scavio_extract: scavioExtract() },
98
+ stopWhen: stepCountIs(3),
99
+ prompt: "Summarise the pricing page at https://scavio.dev/pricing",
100
+ });
101
+ ```
102
+
103
+ `scavio_extract` takes `url` plus an optional `format` (`markdown` default, `text`, `html`) and
104
+ `mode`. `mode` is the price-bearing param: `normal` is a plain fetch (1 credit), `advanced` renders
105
+ the page in a browser for JS-built sites (1 credit), and `ultra` routes through residential proxies
106
+ for the hardest bot walls (2 credits). Only a successful read is billed - a dead link, a bot wall or
107
+ a timeout costs nothing. See [the extract docs](https://scavio.dev/docs/extract).
108
+
109
+ These tools cover the most common surfaces. The full Scavio API - 195 endpoints across 31 platforms
110
+ (Google, YouTube, Amazon, Walmart, Reddit, TikTok, TikTok Shop, Instagram, X, LinkedIn, eBay, Target,
111
+ Home Depot, Zillow, Redfin, Booking, Airbnb, Tripadvisor, Yelp, Indeed, Glassdoor, the App Store,
112
+ Google Play, SEC, Companies House, G2, Capterra, Google Ads, Meta Ad Library, Threads and Kuaishou),
113
+ plus `extract` - is available directly through the
114
+ [`scavio`](https://www.npmjs.com/package/scavio) SDK or the [MCP server](https://scavio.dev/docs).
55
115
 
56
116
  ## License
57
117
 
package/dist/index.cjs CHANGED
@@ -20,14 +20,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ scavioAmazonOffers: () => scavioAmazonOffers,
23
24
  scavioAmazonSearch: () => scavioAmazonSearch,
25
+ scavioExtract: () => scavioExtract,
24
26
  scavioInstagramSearch: () => scavioInstagramSearch,
25
27
  scavioRedditSearch: () => scavioRedditSearch,
26
28
  scavioSearch: () => scavioSearch,
27
29
  scavioTiktokSearch: () => scavioTiktokSearch,
28
30
  scavioTools: () => scavioTools,
29
31
  scavioWalmartSearch: () => scavioWalmartSearch,
30
- scavioYoutubeSearch: () => scavioYoutubeSearch
32
+ scavioYoutubeChannel: () => scavioYoutubeChannel,
33
+ scavioYoutubeComments: () => scavioYoutubeComments,
34
+ scavioYoutubeSearch: () => scavioYoutubeSearch,
35
+ scavioYoutubeTranscript: () => scavioYoutubeTranscript,
36
+ scavioYoutubeVideo: () => scavioYoutubeVideo
31
37
  });
32
38
  module.exports = __toCommonJS(index_exports);
33
39
  var import_ai = require("ai");
@@ -36,20 +42,40 @@ var import_scavio = require("scavio");
36
42
  function client(config) {
37
43
  return new import_scavio.Scavio({ apiKey: config?.apiKey });
38
44
  }
39
- function trim(res, max) {
40
- const results = res.results;
41
- if (Array.isArray(results) && results.length > max) {
42
- return { ...res, results: results.slice(0, max) };
45
+ function trimFlat(res, key, max) {
46
+ const list = res[key];
47
+ if (Array.isArray(list) && list.length > max) {
48
+ return { ...res, [key]: list.slice(0, max) };
43
49
  }
44
50
  return res;
45
51
  }
46
- function trimList(res, key, max) {
47
- const list = res[key];
52
+ function trimData(res, key, max) {
53
+ const data = res.data;
54
+ if (!data || typeof data !== "object") return res;
55
+ const list = data[key];
48
56
  if (Array.isArray(list) && list.length > max) {
49
- return { ...res, [key]: list.slice(0, max) };
57
+ return { ...res, data: { ...data, [key]: list.slice(0, max) } };
50
58
  }
51
59
  return res;
52
60
  }
61
+ function scavioExtract(config) {
62
+ const c = client(config);
63
+ return (0, import_ai.tool)({
64
+ description: "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.",
65
+ inputSchema: import_zod.z.object({
66
+ url: import_zod.z.string().describe(
67
+ "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."
68
+ ),
69
+ format: import_zod.z.enum(["html", "markdown", "text"]).optional().describe(
70
+ "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
+ ),
72
+ 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 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'."
74
+ )
75
+ }),
76
+ execute: async ({ url, format, mode }) => c.extract({ url, format, mode })
77
+ });
78
+ }
53
79
  function scavioSearch(config) {
54
80
  const c = client(config);
55
81
  const max = config?.maxResults ?? 10;
@@ -70,7 +96,7 @@ function scavioSearch(config) {
70
96
  if (page && page > 1) params.start = (page - 1) * 10;
71
97
  if (device) params.device = device;
72
98
  if (nfpr !== void 0) params.nfpr = nfpr;
73
- return trimList(await c.google.search(params), "organic_results", max);
99
+ return trimFlat(await c.google.search(params), "organic_results", max);
74
100
  }
75
101
  });
76
102
  }
@@ -78,64 +104,138 @@ function scavioYoutubeSearch(config) {
78
104
  const c = client(config);
79
105
  const max = config?.maxResults ?? 10;
80
106
  return (0, import_ai.tool)({
81
- description: "Search YouTube for videos via the Scavio API.",
107
+ description: "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.",
108
+ inputSchema: import_zod.z.object({
109
+ query: import_zod.z.string().describe("The search query."),
110
+ upload_date: import_zod.z.string().optional().describe("Upload date filter, e.g. 'today', 'this_week', 'this_month'."),
111
+ type: import_zod.z.string().optional().describe("Result type: 'video', 'channel', 'playlist', 'movie'."),
112
+ duration: import_zod.z.string().optional().describe("Duration filter: 'short', 'medium', 'long'."),
113
+ sort_by: import_zod.z.string().optional().describe("Sort order: 'relevance', 'date', 'view_count', 'rating'."),
114
+ cursor: import_zod.z.string().optional().describe("Pagination cursor (`next_cursor`) from a prior response.")
115
+ }),
116
+ execute: async ({ query, upload_date, type, duration, sort_by, cursor }) => trimData(
117
+ await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor }),
118
+ "results",
119
+ max
120
+ )
121
+ });
122
+ }
123
+ function scavioYoutubeVideo(config) {
124
+ const c = client(config);
125
+ return (0, import_ai.tool)({
126
+ description: "Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.",
127
+ inputSchema: import_zod.z.object({
128
+ video_id: import_zod.z.string().describe("YouTube video id or a full watch URL.")
129
+ }),
130
+ execute: async ({ video_id }) => c.youtube.video({ video_id })
131
+ });
132
+ }
133
+ function scavioYoutubeTranscript(config) {
134
+ const c = client(config);
135
+ return (0, import_ai.tool)({
136
+ description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (8 credits).",
137
+ inputSchema: import_zod.z.object({
138
+ video_id: import_zod.z.string().describe("YouTube video id or a full watch URL."),
139
+ language: import_zod.z.string().optional().describe("Transcript language code (default 'en')."),
140
+ format: import_zod.z.enum(["text", "srt"]).optional().describe("'text' for a plain transcript, 'srt' for timed subtitles.")
141
+ }),
142
+ execute: async ({ video_id, language, format }) => c.youtube.transcript({ video_id, language, format })
143
+ });
144
+ }
145
+ function scavioYoutubeComments(config) {
146
+ const c = client(config);
147
+ const max = config?.maxResults ?? 10;
148
+ return (0, import_ai.tool)({
149
+ description: "List comments on a YouTube video via the Scavio API.",
150
+ inputSchema: import_zod.z.object({
151
+ video_id: import_zod.z.string().describe("YouTube video id or a full watch URL."),
152
+ cursor: import_zod.z.string().optional().describe("Pagination cursor.")
153
+ }),
154
+ execute: async ({ video_id, cursor }) => trimData(
155
+ await c.youtube.comments({ video_id, cursor }),
156
+ "comments",
157
+ max
158
+ )
159
+ });
160
+ }
161
+ function scavioYoutubeChannel(config) {
162
+ const c = client(config);
163
+ return (0, import_ai.tool)({
164
+ description: "Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.",
82
165
  inputSchema: import_zod.z.object({
83
- query: import_zod.z.string().describe("The search query.")
166
+ channel_id: import_zod.z.string().describe("YouTube channel id, @handle, or channel URL.")
84
167
  }),
85
- execute: async ({ query }) => trim(await c.youtube.search({ query }), max)
168
+ execute: async ({ channel_id }) => c.youtube.channel({ channel_id })
86
169
  });
87
170
  }
88
171
  function scavioRedditSearch(config) {
89
172
  const c = client(config);
90
173
  const max = config?.maxResults ?? 10;
91
174
  return (0, import_ai.tool)({
92
- description: "Search Reddit posts and communities via the Scavio API.",
175
+ description: "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.",
93
176
  inputSchema: import_zod.z.object({
94
177
  query: import_zod.z.string().describe("The search query."),
95
- sort: import_zod.z.string().optional().describe("Sort order for results.")
178
+ cursor: import_zod.z.string().optional().describe("Pagination cursor (`next_cursor`) from a prior response.")
96
179
  }),
97
- execute: async ({ query, sort }) => trim(await c.reddit.search({ query, sort }), max)
180
+ execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), "results", max)
98
181
  });
99
182
  }
100
183
  function scavioAmazonSearch(config) {
101
184
  const c = client(config);
102
185
  const max = config?.maxResults ?? 10;
103
186
  return (0, import_ai.tool)({
104
- description: "Search Amazon for products via the Scavio API.",
187
+ description: "Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.",
105
188
  inputSchema: import_zod.z.object({
106
189
  query: import_zod.z.string().describe("The product search query."),
107
- domain: import_zod.z.string().optional().describe('Amazon domain, e.g. "amazon.com".')
190
+ country: import_zod.z.string().optional().describe(
191
+ "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."
192
+ )
193
+ }),
194
+ execute: async ({ query, country }) => trimData(await c.amazon.search({ query, country }), "products", max)
195
+ });
196
+ }
197
+ function scavioAmazonOffers(config) {
198
+ const c = client(config);
199
+ const max = config?.maxResults ?? 10;
200
+ return (0, import_ai.tool)({
201
+ description: "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.",
202
+ inputSchema: import_zod.z.object({
203
+ asin: import_zod.z.string().describe("Amazon Standard Identification Number (ASIN) of the product."),
204
+ country: import_zod.z.string().optional().describe(
205
+ "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."
206
+ )
108
207
  }),
109
- execute: async ({ query, domain }) => trim(await c.amazon.search({ query, domain }), max)
208
+ execute: async ({ asin, country }) => trimData(await c.amazon.offers({ asin, country }), "offers", max)
110
209
  });
111
210
  }
112
211
  function scavioWalmartSearch(config) {
113
212
  const c = client(config);
114
213
  const max = config?.maxResults ?? 10;
115
214
  return (0, import_ai.tool)({
116
- description: "Search Walmart for products via the Scavio API.",
215
+ description: "Search Walmart for products via the Scavio API. Products come back under `data.products`.",
117
216
  inputSchema: import_zod.z.object({
118
217
  query: import_zod.z.string().describe("The product search query.")
119
218
  }),
120
- execute: async ({ query }) => trim(await c.walmart.search({ query }), max)
219
+ execute: async ({ query }) => trimData(await c.walmart.search({ query }), "products", max)
121
220
  });
122
221
  }
123
222
  function scavioTiktokSearch(config) {
124
223
  const c = client(config);
125
224
  const max = config?.maxResults ?? 10;
126
225
  return (0, import_ai.tool)({
127
- description: "Search TikTok for videos by keyword via the Scavio API.",
226
+ description: "Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.",
128
227
  inputSchema: import_zod.z.object({
129
228
  keyword: import_zod.z.string().describe("The search keyword."),
130
- sort_type: import_zod.z.string().optional().describe("Sort order for results."),
131
- publish_time: import_zod.z.string().optional().describe("Filter by publish time window.")
229
+ sort_type: import_zod.z.enum(["0", "1"]).optional().describe("Sort order: '0' relevance, '1' most likes."),
230
+ publish_time: import_zod.z.enum(["0", "1", "7", "30", "90", "180"]).optional().describe("Publish window in days: '0' all time, '1', '7', '30', '90', '180'.")
132
231
  }),
133
- execute: async ({ keyword, sort_type, publish_time }) => trim(
232
+ execute: async ({ keyword, sort_type, publish_time }) => trimData(
134
233
  await c.tiktok.searchVideos({
135
234
  keyword,
136
235
  sort_type,
137
236
  publish_time
138
237
  }),
238
+ "aweme_list",
139
239
  max
140
240
  )
141
241
  });
@@ -144,19 +244,25 @@ function scavioInstagramSearch(config) {
144
244
  const c = client(config);
145
245
  const max = config?.maxResults ?? 10;
146
246
  return (0, import_ai.tool)({
147
- description: "Search Instagram for users by keyword via the Scavio API.",
247
+ description: "Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.",
148
248
  inputSchema: import_zod.z.object({
149
249
  keyword: import_zod.z.string().describe("The search keyword.")
150
250
  }),
151
- execute: async ({ keyword }) => trim(await c.instagram.searchUsers({ keyword }), max)
251
+ execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), "users", max)
152
252
  });
153
253
  }
154
254
  function scavioTools(config) {
155
255
  return {
256
+ scavio_extract: scavioExtract(config),
156
257
  scavio_search: scavioSearch(config),
157
258
  scavio_youtube_search: scavioYoutubeSearch(config),
259
+ scavio_youtube_video: scavioYoutubeVideo(config),
260
+ scavio_youtube_transcript: scavioYoutubeTranscript(config),
261
+ scavio_youtube_comments: scavioYoutubeComments(config),
262
+ scavio_youtube_channel: scavioYoutubeChannel(config),
158
263
  scavio_reddit_search: scavioRedditSearch(config),
159
264
  scavio_amazon_search: scavioAmazonSearch(config),
265
+ scavio_amazon_offers: scavioAmazonOffers(config),
160
266
  scavio_walmart_search: scavioWalmartSearch(config),
161
267
  scavio_tiktok_search: scavioTiktokSearch(config),
162
268
  scavio_instagram_search: scavioInstagramSearch(config)
@@ -164,13 +270,19 @@ function scavioTools(config) {
164
270
  }
165
271
  // Annotate the CommonJS export names for ESM import in node:
166
272
  0 && (module.exports = {
273
+ scavioAmazonOffers,
167
274
  scavioAmazonSearch,
275
+ scavioExtract,
168
276
  scavioInstagramSearch,
169
277
  scavioRedditSearch,
170
278
  scavioSearch,
171
279
  scavioTiktokSearch,
172
280
  scavioTools,
173
281
  scavioWalmartSearch,
174
- scavioYoutubeSearch
282
+ scavioYoutubeChannel,
283
+ scavioYoutubeComments,
284
+ scavioYoutubeSearch,
285
+ scavioYoutubeTranscript,
286
+ scavioYoutubeVideo
175
287
  });
176
288
  //# sourceMappingURL=index.cjs.map
@@ -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 /** Max number of results to keep in `results`-style lists. Defaults to 10. */\n maxResults?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\nfunction trim(res: Record<string, unknown>, max: number): Record<string, unknown> {\n const results = res.results;\n if (Array.isArray(results) && results.length > max) {\n return { ...res, results: results.slice(0, max) };\n }\n return res;\n}\n\nfunction trimList(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/** 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 trimList(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search. */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search YouTube for videos via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n }),\n execute: async ({ query }) => trim(await c.youtube.search({ query }), max),\n });\n}\n\n/** Reddit post/community search (costs 2 credits). */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Reddit posts and communities via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n sort: z.string().optional().describe(\"Sort order for results.\"),\n }),\n execute: async ({ query, sort }) =>\n trim(await c.reddit.search({ query, sort } as Parameters<typeof c.reddit.search>[0]), max),\n });\n}\n\n/** Amazon product search. */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Amazon for products via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n domain: z.string().optional().describe('Amazon domain, e.g. \"amazon.com\".'),\n }),\n execute: async ({ query, domain }) => trim(await c.amazon.search({ query, domain }), 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.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trim(await c.walmart.search({ query }), 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: \"Search TikTok for videos by keyword via the Scavio API.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.string().optional().describe(\"Sort order for results.\"),\n publish_time: z.string().optional().describe(\"Filter by publish time window.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trim(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\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: \"Search Instagram for users by keyword via the Scavio API.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trim(await c.instagram.searchUsers({ keyword }), 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_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(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\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":[]}
package/dist/index.d.cts CHANGED
@@ -2,9 +2,29 @@ import * as ai from 'ai';
2
2
  import { ScavioConfig } from 'scavio';
3
3
 
4
4
  interface ScavioToolConfig extends ScavioConfig {
5
- /** Max number of results to keep in `results`-style lists. Defaults to 10. */
5
+ /**
6
+ * Max number of items to keep in the tool's result list. Defaults to 10.
7
+ * Trimmed inside `data` on every platform except Google, whose body is flat.
8
+ * Ignored by `scavioExtract`, which returns page content rather than a list.
9
+ */
6
10
  maxResults?: number;
7
11
  }
12
+ /**
13
+ * Read any URL (/api/v1/extract).
14
+ *
15
+ * The one tool here that is not tied to a platform, and the only one `maxResults`
16
+ * does not touch: extract returns page CONTENT, not a result list, so there is
17
+ * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL
18
+ * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.
19
+ *
20
+ * Credits are a function of `mode`, not a per-call constant: "normal" 1,
21
+ * "advanced" 1, "ultra" 2. Only a successful read is billed.
22
+ */
23
+ declare function scavioExtract(config?: ScavioToolConfig): ai.Tool<{
24
+ url: string;
25
+ format?: "html" | "markdown" | "text" | undefined;
26
+ mode?: "normal" | "advanced" | "ultra" | undefined;
27
+ }, Record<string, unknown>>;
8
28
  /** Google web search (/api/v2/google, 1 credit). */
9
29
  declare function scavioSearch(config?: ScavioToolConfig): ai.Tool<{
10
30
  query: string;
@@ -14,19 +34,61 @@ declare function scavioSearch(config?: ScavioToolConfig): ai.Tool<{
14
34
  device?: "desktop" | "mobile" | undefined;
15
35
  nfpr?: boolean | undefined;
16
36
  }, Record<string, unknown>>;
17
- /** YouTube video search. */
37
+ /** YouTube video search (2 credits). */
18
38
  declare function scavioYoutubeSearch(config?: ScavioToolConfig): ai.Tool<{
19
39
  query: string;
40
+ type?: string | undefined;
41
+ upload_date?: string | undefined;
42
+ duration?: string | undefined;
43
+ sort_by?: string | undefined;
44
+ cursor?: string | undefined;
45
+ }, Record<string, unknown>>;
46
+ /** YouTube video details (1 credit). */
47
+ declare function scavioYoutubeVideo(config?: ScavioToolConfig): ai.Tool<{
48
+ video_id: string;
49
+ }, Record<string, unknown>>;
50
+ /** YouTube video transcript / subtitles (8 credits). */
51
+ declare function scavioYoutubeTranscript(config?: ScavioToolConfig): ai.Tool<{
52
+ video_id: string;
53
+ format?: "text" | "srt" | undefined;
54
+ language?: string | undefined;
55
+ }, Record<string, unknown>>;
56
+ /** YouTube video comments (1 credit). */
57
+ declare function scavioYoutubeComments(config?: ScavioToolConfig): ai.Tool<{
58
+ video_id: string;
59
+ cursor?: string | undefined;
60
+ }, Record<string, unknown>>;
61
+ /** YouTube channel details (1 credit). */
62
+ declare function scavioYoutubeChannel(config?: ScavioToolConfig): ai.Tool<{
63
+ channel_id: string;
20
64
  }, Record<string, unknown>>;
21
- /** Reddit post/community search (costs 2 credits). */
65
+ /**
66
+ * Reddit post search (1 credit).
67
+ *
68
+ * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or
69
+ * filter by type, so no such input is offered. The API silently ignores those
70
+ * params, which would leave a model believing it had filtered when it had not.
71
+ */
22
72
  declare function scavioRedditSearch(config?: ScavioToolConfig): ai.Tool<{
23
73
  query: string;
24
- sort?: string | undefined;
74
+ cursor?: string | undefined;
25
75
  }, Record<string, unknown>>;
26
- /** Amazon product search. */
76
+ /**
77
+ * Amazon product search.
78
+ *
79
+ * `domain` was dropped in favour of `country`, a two-letter marketplace code -
80
+ * the upstream provider changed in 2026-07 and no longer takes a domain
81
+ * suffix. It still works on the wire as a deprecated alias, but a model should
82
+ * only ever see one spelling of a param.
83
+ */
27
84
  declare function scavioAmazonSearch(config?: ScavioToolConfig): ai.Tool<{
28
85
  query: string;
29
- domain?: string | undefined;
86
+ country?: string | undefined;
87
+ }, Record<string, unknown>>;
88
+ /** Every seller offer for one Amazon ASIN. */
89
+ declare function scavioAmazonOffers(config?: ScavioToolConfig): ai.Tool<{
90
+ asin: string;
91
+ country?: string | undefined;
30
92
  }, Record<string, unknown>>;
31
93
  /** Walmart product search. */
32
94
  declare function scavioWalmartSearch(config?: ScavioToolConfig): ai.Tool<{
@@ -35,8 +97,8 @@ declare function scavioWalmartSearch(config?: ScavioToolConfig): ai.Tool<{
35
97
  /** TikTok video search. */
36
98
  declare function scavioTiktokSearch(config?: ScavioToolConfig): ai.Tool<{
37
99
  keyword: string;
38
- sort_type?: string | undefined;
39
- publish_time?: string | undefined;
100
+ sort_type?: "0" | "1" | undefined;
101
+ publish_time?: "0" | "1" | "7" | "30" | "90" | "180" | undefined;
40
102
  }, Record<string, unknown>>;
41
103
  /** Instagram user search. */
42
104
  declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
@@ -47,6 +109,11 @@ declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
47
109
  * `tools` option of `generateText` / `streamText`.
48
110
  */
49
111
  declare function scavioTools(config?: ScavioToolConfig): {
112
+ scavio_extract: ai.Tool<{
113
+ url: string;
114
+ format?: "html" | "markdown" | "text" | undefined;
115
+ mode?: "normal" | "advanced" | "ultra" | undefined;
116
+ }, Record<string, unknown>>;
50
117
  scavio_search: ai.Tool<{
51
118
  query: string;
52
119
  countryCode?: string | undefined;
@@ -57,26 +124,50 @@ declare function scavioTools(config?: ScavioToolConfig): {
57
124
  }, Record<string, unknown>>;
58
125
  scavio_youtube_search: ai.Tool<{
59
126
  query: string;
127
+ type?: string | undefined;
128
+ upload_date?: string | undefined;
129
+ duration?: string | undefined;
130
+ sort_by?: string | undefined;
131
+ cursor?: string | undefined;
132
+ }, Record<string, unknown>>;
133
+ scavio_youtube_video: ai.Tool<{
134
+ video_id: string;
135
+ }, Record<string, unknown>>;
136
+ scavio_youtube_transcript: ai.Tool<{
137
+ video_id: string;
138
+ format?: "text" | "srt" | undefined;
139
+ language?: string | undefined;
140
+ }, Record<string, unknown>>;
141
+ scavio_youtube_comments: ai.Tool<{
142
+ video_id: string;
143
+ cursor?: string | undefined;
144
+ }, Record<string, unknown>>;
145
+ scavio_youtube_channel: ai.Tool<{
146
+ channel_id: string;
60
147
  }, Record<string, unknown>>;
61
148
  scavio_reddit_search: ai.Tool<{
62
149
  query: string;
63
- sort?: string | undefined;
150
+ cursor?: string | undefined;
64
151
  }, Record<string, unknown>>;
65
152
  scavio_amazon_search: ai.Tool<{
66
153
  query: string;
67
- domain?: string | undefined;
154
+ country?: string | undefined;
155
+ }, Record<string, unknown>>;
156
+ scavio_amazon_offers: ai.Tool<{
157
+ asin: string;
158
+ country?: string | undefined;
68
159
  }, Record<string, unknown>>;
69
160
  scavio_walmart_search: ai.Tool<{
70
161
  query: string;
71
162
  }, Record<string, unknown>>;
72
163
  scavio_tiktok_search: ai.Tool<{
73
164
  keyword: string;
74
- sort_type?: string | undefined;
75
- publish_time?: string | undefined;
165
+ sort_type?: "0" | "1" | undefined;
166
+ publish_time?: "0" | "1" | "7" | "30" | "90" | "180" | undefined;
76
167
  }, Record<string, unknown>>;
77
168
  scavio_instagram_search: ai.Tool<{
78
169
  keyword: string;
79
170
  }, Record<string, unknown>>;
80
171
  };
81
172
 
82
- export { type ScavioToolConfig, scavioAmazonSearch, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeSearch };
173
+ export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioExtract, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
package/dist/index.d.ts CHANGED
@@ -2,9 +2,29 @@ import * as ai from 'ai';
2
2
  import { ScavioConfig } from 'scavio';
3
3
 
4
4
  interface ScavioToolConfig extends ScavioConfig {
5
- /** Max number of results to keep in `results`-style lists. Defaults to 10. */
5
+ /**
6
+ * Max number of items to keep in the tool's result list. Defaults to 10.
7
+ * Trimmed inside `data` on every platform except Google, whose body is flat.
8
+ * Ignored by `scavioExtract`, which returns page content rather than a list.
9
+ */
6
10
  maxResults?: number;
7
11
  }
12
+ /**
13
+ * Read any URL (/api/v1/extract).
14
+ *
15
+ * The one tool here that is not tied to a platform, and the only one `maxResults`
16
+ * does not touch: extract returns page CONTENT, not a result list, so there is
17
+ * nothing to trim and the body is returned whole. `extract` is a TOP-LEVEL
18
+ * method on the SDK client - `c.extract({ url })`, never `c.extract.extract()`.
19
+ *
20
+ * Credits are a function of `mode`, not a per-call constant: "normal" 1,
21
+ * "advanced" 1, "ultra" 2. Only a successful read is billed.
22
+ */
23
+ declare function scavioExtract(config?: ScavioToolConfig): ai.Tool<{
24
+ url: string;
25
+ format?: "html" | "markdown" | "text" | undefined;
26
+ mode?: "normal" | "advanced" | "ultra" | undefined;
27
+ }, Record<string, unknown>>;
8
28
  /** Google web search (/api/v2/google, 1 credit). */
9
29
  declare function scavioSearch(config?: ScavioToolConfig): ai.Tool<{
10
30
  query: string;
@@ -14,19 +34,61 @@ declare function scavioSearch(config?: ScavioToolConfig): ai.Tool<{
14
34
  device?: "desktop" | "mobile" | undefined;
15
35
  nfpr?: boolean | undefined;
16
36
  }, Record<string, unknown>>;
17
- /** YouTube video search. */
37
+ /** YouTube video search (2 credits). */
18
38
  declare function scavioYoutubeSearch(config?: ScavioToolConfig): ai.Tool<{
19
39
  query: string;
40
+ type?: string | undefined;
41
+ upload_date?: string | undefined;
42
+ duration?: string | undefined;
43
+ sort_by?: string | undefined;
44
+ cursor?: string | undefined;
45
+ }, Record<string, unknown>>;
46
+ /** YouTube video details (1 credit). */
47
+ declare function scavioYoutubeVideo(config?: ScavioToolConfig): ai.Tool<{
48
+ video_id: string;
49
+ }, Record<string, unknown>>;
50
+ /** YouTube video transcript / subtitles (8 credits). */
51
+ declare function scavioYoutubeTranscript(config?: ScavioToolConfig): ai.Tool<{
52
+ video_id: string;
53
+ format?: "text" | "srt" | undefined;
54
+ language?: string | undefined;
55
+ }, Record<string, unknown>>;
56
+ /** YouTube video comments (1 credit). */
57
+ declare function scavioYoutubeComments(config?: ScavioToolConfig): ai.Tool<{
58
+ video_id: string;
59
+ cursor?: string | undefined;
60
+ }, Record<string, unknown>>;
61
+ /** YouTube channel details (1 credit). */
62
+ declare function scavioYoutubeChannel(config?: ScavioToolConfig): ai.Tool<{
63
+ channel_id: string;
20
64
  }, Record<string, unknown>>;
21
- /** Reddit post/community search (costs 2 credits). */
65
+ /**
66
+ * Reddit post search (1 credit).
67
+ *
68
+ * The endpoint takes `query` and `cursor` and nothing else - it cannot sort or
69
+ * filter by type, so no such input is offered. The API silently ignores those
70
+ * params, which would leave a model believing it had filtered when it had not.
71
+ */
22
72
  declare function scavioRedditSearch(config?: ScavioToolConfig): ai.Tool<{
23
73
  query: string;
24
- sort?: string | undefined;
74
+ cursor?: string | undefined;
25
75
  }, Record<string, unknown>>;
26
- /** Amazon product search. */
76
+ /**
77
+ * Amazon product search.
78
+ *
79
+ * `domain` was dropped in favour of `country`, a two-letter marketplace code -
80
+ * the upstream provider changed in 2026-07 and no longer takes a domain
81
+ * suffix. It still works on the wire as a deprecated alias, but a model should
82
+ * only ever see one spelling of a param.
83
+ */
27
84
  declare function scavioAmazonSearch(config?: ScavioToolConfig): ai.Tool<{
28
85
  query: string;
29
- domain?: string | undefined;
86
+ country?: string | undefined;
87
+ }, Record<string, unknown>>;
88
+ /** Every seller offer for one Amazon ASIN. */
89
+ declare function scavioAmazonOffers(config?: ScavioToolConfig): ai.Tool<{
90
+ asin: string;
91
+ country?: string | undefined;
30
92
  }, Record<string, unknown>>;
31
93
  /** Walmart product search. */
32
94
  declare function scavioWalmartSearch(config?: ScavioToolConfig): ai.Tool<{
@@ -35,8 +97,8 @@ declare function scavioWalmartSearch(config?: ScavioToolConfig): ai.Tool<{
35
97
  /** TikTok video search. */
36
98
  declare function scavioTiktokSearch(config?: ScavioToolConfig): ai.Tool<{
37
99
  keyword: string;
38
- sort_type?: string | undefined;
39
- publish_time?: string | undefined;
100
+ sort_type?: "0" | "1" | undefined;
101
+ publish_time?: "0" | "1" | "7" | "30" | "90" | "180" | undefined;
40
102
  }, Record<string, unknown>>;
41
103
  /** Instagram user search. */
42
104
  declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
@@ -47,6 +109,11 @@ declare function scavioInstagramSearch(config?: ScavioToolConfig): ai.Tool<{
47
109
  * `tools` option of `generateText` / `streamText`.
48
110
  */
49
111
  declare function scavioTools(config?: ScavioToolConfig): {
112
+ scavio_extract: ai.Tool<{
113
+ url: string;
114
+ format?: "html" | "markdown" | "text" | undefined;
115
+ mode?: "normal" | "advanced" | "ultra" | undefined;
116
+ }, Record<string, unknown>>;
50
117
  scavio_search: ai.Tool<{
51
118
  query: string;
52
119
  countryCode?: string | undefined;
@@ -57,26 +124,50 @@ declare function scavioTools(config?: ScavioToolConfig): {
57
124
  }, Record<string, unknown>>;
58
125
  scavio_youtube_search: ai.Tool<{
59
126
  query: string;
127
+ type?: string | undefined;
128
+ upload_date?: string | undefined;
129
+ duration?: string | undefined;
130
+ sort_by?: string | undefined;
131
+ cursor?: string | undefined;
132
+ }, Record<string, unknown>>;
133
+ scavio_youtube_video: ai.Tool<{
134
+ video_id: string;
135
+ }, Record<string, unknown>>;
136
+ scavio_youtube_transcript: ai.Tool<{
137
+ video_id: string;
138
+ format?: "text" | "srt" | undefined;
139
+ language?: string | undefined;
140
+ }, Record<string, unknown>>;
141
+ scavio_youtube_comments: ai.Tool<{
142
+ video_id: string;
143
+ cursor?: string | undefined;
144
+ }, Record<string, unknown>>;
145
+ scavio_youtube_channel: ai.Tool<{
146
+ channel_id: string;
60
147
  }, Record<string, unknown>>;
61
148
  scavio_reddit_search: ai.Tool<{
62
149
  query: string;
63
- sort?: string | undefined;
150
+ cursor?: string | undefined;
64
151
  }, Record<string, unknown>>;
65
152
  scavio_amazon_search: ai.Tool<{
66
153
  query: string;
67
- domain?: string | undefined;
154
+ country?: string | undefined;
155
+ }, Record<string, unknown>>;
156
+ scavio_amazon_offers: ai.Tool<{
157
+ asin: string;
158
+ country?: string | undefined;
68
159
  }, Record<string, unknown>>;
69
160
  scavio_walmart_search: ai.Tool<{
70
161
  query: string;
71
162
  }, Record<string, unknown>>;
72
163
  scavio_tiktok_search: ai.Tool<{
73
164
  keyword: string;
74
- sort_type?: string | undefined;
75
- publish_time?: string | undefined;
165
+ sort_type?: "0" | "1" | undefined;
166
+ publish_time?: "0" | "1" | "7" | "30" | "90" | "180" | undefined;
76
167
  }, Record<string, unknown>>;
77
168
  scavio_instagram_search: ai.Tool<{
78
169
  keyword: string;
79
170
  }, Record<string, unknown>>;
80
171
  };
81
172
 
82
- export { type ScavioToolConfig, scavioAmazonSearch, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeSearch };
173
+ export { type ScavioToolConfig, scavioAmazonOffers, scavioAmazonSearch, scavioExtract, scavioInstagramSearch, scavioRedditSearch, scavioSearch, scavioTiktokSearch, scavioTools, scavioWalmartSearch, scavioYoutubeChannel, scavioYoutubeComments, scavioYoutubeSearch, scavioYoutubeTranscript, scavioYoutubeVideo };
package/dist/index.js CHANGED
@@ -5,20 +5,40 @@ import { Scavio } from "scavio";
5
5
  function client(config) {
6
6
  return new Scavio({ apiKey: config?.apiKey });
7
7
  }
8
- function trim(res, max) {
9
- const results = res.results;
10
- if (Array.isArray(results) && results.length > max) {
11
- return { ...res, results: results.slice(0, max) };
8
+ function trimFlat(res, key, max) {
9
+ const list = res[key];
10
+ if (Array.isArray(list) && list.length > max) {
11
+ return { ...res, [key]: list.slice(0, max) };
12
12
  }
13
13
  return res;
14
14
  }
15
- function trimList(res, key, max) {
16
- const list = res[key];
15
+ function trimData(res, key, max) {
16
+ const data = res.data;
17
+ if (!data || typeof data !== "object") return res;
18
+ const list = data[key];
17
19
  if (Array.isArray(list) && list.length > max) {
18
- return { ...res, [key]: list.slice(0, max) };
20
+ return { ...res, data: { ...data, [key]: list.slice(0, max) } };
19
21
  }
20
22
  return res;
21
23
  }
24
+ function scavioExtract(config) {
25
+ const c = client(config);
26
+ return tool({
27
+ description: "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.",
28
+ inputSchema: z.object({
29
+ url: z.string().describe(
30
+ "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."
31
+ ),
32
+ format: z.enum(["html", "markdown", "text"]).optional().describe(
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
+ ),
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 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'."
37
+ )
38
+ }),
39
+ execute: async ({ url, format, mode }) => c.extract({ url, format, mode })
40
+ });
41
+ }
22
42
  function scavioSearch(config) {
23
43
  const c = client(config);
24
44
  const max = config?.maxResults ?? 10;
@@ -39,7 +59,7 @@ function scavioSearch(config) {
39
59
  if (page && page > 1) params.start = (page - 1) * 10;
40
60
  if (device) params.device = device;
41
61
  if (nfpr !== void 0) params.nfpr = nfpr;
42
- return trimList(await c.google.search(params), "organic_results", max);
62
+ return trimFlat(await c.google.search(params), "organic_results", max);
43
63
  }
44
64
  });
45
65
  }
@@ -47,64 +67,138 @@ function scavioYoutubeSearch(config) {
47
67
  const c = client(config);
48
68
  const max = config?.maxResults ?? 10;
49
69
  return tool({
50
- description: "Search YouTube for videos via the Scavio API.",
70
+ description: "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.",
71
+ inputSchema: z.object({
72
+ query: z.string().describe("The search query."),
73
+ upload_date: z.string().optional().describe("Upload date filter, e.g. 'today', 'this_week', 'this_month'."),
74
+ type: z.string().optional().describe("Result type: 'video', 'channel', 'playlist', 'movie'."),
75
+ duration: z.string().optional().describe("Duration filter: 'short', 'medium', 'long'."),
76
+ sort_by: z.string().optional().describe("Sort order: 'relevance', 'date', 'view_count', 'rating'."),
77
+ cursor: z.string().optional().describe("Pagination cursor (`next_cursor`) from a prior response.")
78
+ }),
79
+ execute: async ({ query, upload_date, type, duration, sort_by, cursor }) => trimData(
80
+ await c.youtube.search({ query, upload_date, type, duration, sort_by, cursor }),
81
+ "results",
82
+ max
83
+ )
84
+ });
85
+ }
86
+ function scavioYoutubeVideo(config) {
87
+ const c = client(config);
88
+ return tool({
89
+ description: "Fetch full details for a YouTube video (title, author, view count, description, captions, chapters) via the Scavio API.",
90
+ inputSchema: z.object({
91
+ video_id: z.string().describe("YouTube video id or a full watch URL.")
92
+ }),
93
+ execute: async ({ video_id }) => c.youtube.video({ video_id })
94
+ });
95
+ }
96
+ function scavioYoutubeTranscript(config) {
97
+ const c = client(config);
98
+ return tool({
99
+ description: "Fetch a YouTube video's transcript or timed subtitles via the Scavio API (8 credits).",
100
+ inputSchema: z.object({
101
+ video_id: z.string().describe("YouTube video id or a full watch URL."),
102
+ language: z.string().optional().describe("Transcript language code (default 'en')."),
103
+ format: z.enum(["text", "srt"]).optional().describe("'text' for a plain transcript, 'srt' for timed subtitles.")
104
+ }),
105
+ execute: async ({ video_id, language, format }) => c.youtube.transcript({ video_id, language, format })
106
+ });
107
+ }
108
+ function scavioYoutubeComments(config) {
109
+ const c = client(config);
110
+ const max = config?.maxResults ?? 10;
111
+ return tool({
112
+ description: "List comments on a YouTube video via the Scavio API.",
113
+ inputSchema: z.object({
114
+ video_id: z.string().describe("YouTube video id or a full watch URL."),
115
+ cursor: z.string().optional().describe("Pagination cursor.")
116
+ }),
117
+ execute: async ({ video_id, cursor }) => trimData(
118
+ await c.youtube.comments({ video_id, cursor }),
119
+ "comments",
120
+ max
121
+ )
122
+ });
123
+ }
124
+ function scavioYoutubeChannel(config) {
125
+ const c = client(config);
126
+ return tool({
127
+ description: "Fetch a YouTube channel's details (subscribers, video count, views, links) via the Scavio API.",
51
128
  inputSchema: z.object({
52
- query: z.string().describe("The search query.")
129
+ channel_id: z.string().describe("YouTube channel id, @handle, or channel URL.")
53
130
  }),
54
- execute: async ({ query }) => trim(await c.youtube.search({ query }), max)
131
+ execute: async ({ channel_id }) => c.youtube.channel({ channel_id })
55
132
  });
56
133
  }
57
134
  function scavioRedditSearch(config) {
58
135
  const c = client(config);
59
136
  const max = config?.maxResults ?? 10;
60
137
  return tool({
61
- description: "Search Reddit posts and communities via the Scavio API.",
138
+ description: "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.",
62
139
  inputSchema: z.object({
63
140
  query: z.string().describe("The search query."),
64
- sort: z.string().optional().describe("Sort order for results.")
141
+ cursor: z.string().optional().describe("Pagination cursor (`next_cursor`) from a prior response.")
65
142
  }),
66
- execute: async ({ query, sort }) => trim(await c.reddit.search({ query, sort }), max)
143
+ execute: async ({ query, cursor }) => trimData(await c.reddit.search({ query, cursor }), "results", max)
67
144
  });
68
145
  }
69
146
  function scavioAmazonSearch(config) {
70
147
  const c = client(config);
71
148
  const max = config?.maxResults ?? 10;
72
149
  return tool({
73
- description: "Search Amazon for products via the Scavio API.",
150
+ description: "Search Amazon for products via the Scavio API. Results are unsorted and cannot be filtered by category, merchant or price.",
74
151
  inputSchema: z.object({
75
152
  query: z.string().describe("The product search query."),
76
- domain: z.string().optional().describe('Amazon domain, e.g. "amazon.com".')
153
+ country: z.string().optional().describe(
154
+ "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."
155
+ )
156
+ }),
157
+ execute: async ({ query, country }) => trimData(await c.amazon.search({ query, country }), "products", max)
158
+ });
159
+ }
160
+ function scavioAmazonOffers(config) {
161
+ const c = client(config);
162
+ const max = config?.maxResults ?? 10;
163
+ return tool({
164
+ description: "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.",
165
+ inputSchema: z.object({
166
+ asin: z.string().describe("Amazon Standard Identification Number (ASIN) of the product."),
167
+ country: z.string().optional().describe(
168
+ "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."
169
+ )
77
170
  }),
78
- execute: async ({ query, domain }) => trim(await c.amazon.search({ query, domain }), max)
171
+ execute: async ({ asin, country }) => trimData(await c.amazon.offers({ asin, country }), "offers", max)
79
172
  });
80
173
  }
81
174
  function scavioWalmartSearch(config) {
82
175
  const c = client(config);
83
176
  const max = config?.maxResults ?? 10;
84
177
  return tool({
85
- description: "Search Walmart for products via the Scavio API.",
178
+ description: "Search Walmart for products via the Scavio API. Products come back under `data.products`.",
86
179
  inputSchema: z.object({
87
180
  query: z.string().describe("The product search query.")
88
181
  }),
89
- execute: async ({ query }) => trim(await c.walmart.search({ query }), max)
182
+ execute: async ({ query }) => trimData(await c.walmart.search({ query }), "products", max)
90
183
  });
91
184
  }
92
185
  function scavioTiktokSearch(config) {
93
186
  const c = client(config);
94
187
  const max = config?.maxResults ?? 10;
95
188
  return tool({
96
- description: "Search TikTok for videos by keyword via the Scavio API.",
189
+ description: "Search TikTok for videos by keyword via the Scavio API. Videos come back under `data.aweme_list`.",
97
190
  inputSchema: z.object({
98
191
  keyword: z.string().describe("The search keyword."),
99
- sort_type: z.string().optional().describe("Sort order for results."),
100
- publish_time: z.string().optional().describe("Filter by publish time window.")
192
+ sort_type: z.enum(["0", "1"]).optional().describe("Sort order: '0' relevance, '1' most likes."),
193
+ publish_time: z.enum(["0", "1", "7", "30", "90", "180"]).optional().describe("Publish window in days: '0' all time, '1', '7', '30', '90', '180'.")
101
194
  }),
102
- execute: async ({ keyword, sort_type, publish_time }) => trim(
195
+ execute: async ({ keyword, sort_type, publish_time }) => trimData(
103
196
  await c.tiktok.searchVideos({
104
197
  keyword,
105
198
  sort_type,
106
199
  publish_time
107
200
  }),
201
+ "aweme_list",
108
202
  max
109
203
  )
110
204
  });
@@ -113,32 +207,44 @@ function scavioInstagramSearch(config) {
113
207
  const c = client(config);
114
208
  const max = config?.maxResults ?? 10;
115
209
  return tool({
116
- description: "Search Instagram for users by keyword via the Scavio API.",
210
+ description: "Search Instagram for users by keyword via the Scavio API (10 credits). Users come back under `data.users`.",
117
211
  inputSchema: z.object({
118
212
  keyword: z.string().describe("The search keyword.")
119
213
  }),
120
- execute: async ({ keyword }) => trim(await c.instagram.searchUsers({ keyword }), max)
214
+ execute: async ({ keyword }) => trimData(await c.instagram.searchUsers({ keyword }), "users", max)
121
215
  });
122
216
  }
123
217
  function scavioTools(config) {
124
218
  return {
219
+ scavio_extract: scavioExtract(config),
125
220
  scavio_search: scavioSearch(config),
126
221
  scavio_youtube_search: scavioYoutubeSearch(config),
222
+ scavio_youtube_video: scavioYoutubeVideo(config),
223
+ scavio_youtube_transcript: scavioYoutubeTranscript(config),
224
+ scavio_youtube_comments: scavioYoutubeComments(config),
225
+ scavio_youtube_channel: scavioYoutubeChannel(config),
127
226
  scavio_reddit_search: scavioRedditSearch(config),
128
227
  scavio_amazon_search: scavioAmazonSearch(config),
228
+ scavio_amazon_offers: scavioAmazonOffers(config),
129
229
  scavio_walmart_search: scavioWalmartSearch(config),
130
230
  scavio_tiktok_search: scavioTiktokSearch(config),
131
231
  scavio_instagram_search: scavioInstagramSearch(config)
132
232
  };
133
233
  }
134
234
  export {
235
+ scavioAmazonOffers,
135
236
  scavioAmazonSearch,
237
+ scavioExtract,
136
238
  scavioInstagramSearch,
137
239
  scavioRedditSearch,
138
240
  scavioSearch,
139
241
  scavioTiktokSearch,
140
242
  scavioTools,
141
243
  scavioWalmartSearch,
142
- scavioYoutubeSearch
244
+ scavioYoutubeChannel,
245
+ scavioYoutubeComments,
246
+ scavioYoutubeSearch,
247
+ scavioYoutubeTranscript,
248
+ scavioYoutubeVideo
143
249
  };
144
250
  //# sourceMappingURL=index.js.map
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 /** Max number of results to keep in `results`-style lists. Defaults to 10. */\n maxResults?: number;\n}\n\nfunction client(config?: ScavioToolConfig): Scavio {\n return new Scavio({ apiKey: config?.apiKey });\n}\n\nfunction trim(res: Record<string, unknown>, max: number): Record<string, unknown> {\n const results = res.results;\n if (Array.isArray(results) && results.length > max) {\n return { ...res, results: results.slice(0, max) };\n }\n return res;\n}\n\nfunction trimList(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/** 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 trimList(await c.google.search(params), \"organic_results\", max);\n },\n });\n}\n\n/** YouTube video search. */\nexport function scavioYoutubeSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search YouTube for videos via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n }),\n execute: async ({ query }) => trim(await c.youtube.search({ query }), max),\n });\n}\n\n/** Reddit post/community search (costs 2 credits). */\nexport function scavioRedditSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Reddit posts and communities via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The search query.\"),\n sort: z.string().optional().describe(\"Sort order for results.\"),\n }),\n execute: async ({ query, sort }) =>\n trim(await c.reddit.search({ query, sort } as Parameters<typeof c.reddit.search>[0]), max),\n });\n}\n\n/** Amazon product search. */\nexport function scavioAmazonSearch(config?: ScavioToolConfig) {\n const c = client(config);\n const max = config?.maxResults ?? 10;\n return tool({\n description: \"Search Amazon for products via the Scavio API.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n domain: z.string().optional().describe('Amazon domain, e.g. \"amazon.com\".'),\n }),\n execute: async ({ query, domain }) => trim(await c.amazon.search({ query, domain }), 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.\",\n inputSchema: z.object({\n query: z.string().describe(\"The product search query.\"),\n }),\n execute: async ({ query }) => trim(await c.walmart.search({ query }), 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: \"Search TikTok for videos by keyword via the Scavio API.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n sort_type: z.string().optional().describe(\"Sort order for results.\"),\n publish_time: z.string().optional().describe(\"Filter by publish time window.\"),\n }),\n execute: async ({ keyword, sort_type, publish_time }) =>\n trim(\n await c.tiktok.searchVideos({\n keyword,\n sort_type,\n publish_time,\n } as Parameters<typeof c.tiktok.searchVideos>[0]),\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: \"Search Instagram for users by keyword via the Scavio API.\",\n inputSchema: z.object({\n keyword: z.string().describe(\"The search keyword.\"),\n }),\n execute: async ({ keyword }) => trim(await c.instagram.searchUsers({ keyword }), 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_search: scavioSearch(config),\n scavio_youtube_search: scavioYoutubeSearch(config),\n scavio_reddit_search: scavioRedditSearch(config),\n scavio_amazon_search: scavioAmazonSearch(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\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":[]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@scavio/ai-sdk",
3
- "version": "0.2.2",
4
- "description": "Scavio search tools for the Vercel AI SDK (Google, YouTube, Reddit, Amazon, Walmart, TikTok, Instagram).",
3
+ "version": "0.4.0",
4
+ "description": "Scavio search and URL-extraction tools for the Vercel AI SDK (extract any URL, plus Google, YouTube, Reddit, Amazon, Walmart, TikTok, Instagram).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.js",
@@ -32,6 +32,8 @@
32
32
  "vercel-ai-sdk",
33
33
  "tools",
34
34
  "search",
35
+ "extract",
36
+ "web-scraping",
35
37
  "agents"
36
38
  ],
37
39
  "license": "MIT",
@@ -48,12 +50,12 @@
48
50
  "zod": ">=3"
49
51
  },
50
52
  "dependencies": {
51
- "scavio": "^0.5.0"
53
+ "scavio": "^0.15.0"
52
54
  },
53
55
  "devDependencies": {
54
56
  "@ai-sdk/openai": "^3.0.74",
55
57
  "ai": "^6.0.208",
56
- "scavio": "^0.5.0",
58
+ "scavio": "^0.15.0",
57
59
  "tsup": "^8.0.0",
58
60
  "typescript": "^5.4.0",
59
61
  "vitest": "^2.0.0",