composio-scavio 0.4.0 → 0.5.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 +68 -6
- package/dist/index.cjs +137 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +137 -2
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.d.cts
CHANGED
|
@@ -36,6 +36,16 @@ interface BuildScavioToolkitOptions {
|
|
|
36
36
|
enableCapterra?: boolean;
|
|
37
37
|
enableGoogleAds?: boolean;
|
|
38
38
|
enableMetaAds?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Website map, crawl and batch extract (five tools: MAP_WEBSITE, CRAWL_WEBSITE,
|
|
41
|
+
* CRAWL_STATUS, BATCH_EXTRACT, BATCH_STATUS). Opt-in: a crawl bills per page.
|
|
42
|
+
*/
|
|
43
|
+
enableCrawl?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Milliseconds between progress polls while CRAWL_WEBSITE or BATCH_EXTRACT
|
|
46
|
+
* waits for its job. Default 3000.
|
|
47
|
+
*/
|
|
48
|
+
pollIntervalMs?: number;
|
|
39
49
|
/** Register every tool, ignoring the individual flags. */
|
|
40
50
|
all?: boolean;
|
|
41
51
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -36,6 +36,16 @@ interface BuildScavioToolkitOptions {
|
|
|
36
36
|
enableCapterra?: boolean;
|
|
37
37
|
enableGoogleAds?: boolean;
|
|
38
38
|
enableMetaAds?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Website map, crawl and batch extract (five tools: MAP_WEBSITE, CRAWL_WEBSITE,
|
|
41
|
+
* CRAWL_STATUS, BATCH_EXTRACT, BATCH_STATUS). Opt-in: a crawl bills per page.
|
|
42
|
+
*/
|
|
43
|
+
enableCrawl?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Milliseconds between progress polls while CRAWL_WEBSITE or BATCH_EXTRACT
|
|
46
|
+
* waits for its job. Default 3000.
|
|
47
|
+
*/
|
|
48
|
+
pollIntervalMs?: number;
|
|
39
49
|
/** Register every tool, ignoring the individual flags. */
|
|
40
50
|
all?: boolean;
|
|
41
51
|
}
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,53 @@ var device = ostr("Device to emulate: 'desktop' or 'mobile'.");
|
|
|
22
22
|
var currency = ostr("Currency code (ISO 4217, e.g. 'USD').");
|
|
23
23
|
var checkInDate = str("Check-in date (YYYY-MM-DD).");
|
|
24
24
|
var checkOutDate = str("Check-out date (YYYY-MM-DD).");
|
|
25
|
+
var JOB_POLL_INTERVAL_MS = 3e3;
|
|
26
|
+
var JOB_WAIT_DEFAULT_SECONDS = 45;
|
|
27
|
+
var JOB_WAIT_MAX_SECONDS = 300;
|
|
28
|
+
var JOB_RESULTS_DEFAULT_LIMIT = 10;
|
|
29
|
+
var JOB_TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
30
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
31
|
+
async function waitForJob(status, id, waitSeconds, pollMs, query) {
|
|
32
|
+
const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1e3;
|
|
33
|
+
for (; ; ) {
|
|
34
|
+
const remaining = deadline - Date.now();
|
|
35
|
+
if (remaining <= 0) break;
|
|
36
|
+
await sleep(Math.min(pollMs, remaining));
|
|
37
|
+
const probe = await status(id, { limit: 1, include_content: false });
|
|
38
|
+
if (JOB_TERMINAL.has(String(probe?.data?.status))) break;
|
|
39
|
+
}
|
|
40
|
+
return await status(id, query);
|
|
41
|
+
}
|
|
42
|
+
async function startAndWait(start, status, input, pollMs) {
|
|
43
|
+
const { wait_seconds, limit, include_content, ...body } = input;
|
|
44
|
+
const created = await start(body);
|
|
45
|
+
const id = created?.data?.id;
|
|
46
|
+
const wait = wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;
|
|
47
|
+
if (!id || wait <= 0) return created;
|
|
48
|
+
const query = { limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT };
|
|
49
|
+
if (include_content !== void 0) query.include_content = include_content;
|
|
50
|
+
return waitForJob(status, id, wait, pollMs, query);
|
|
51
|
+
}
|
|
52
|
+
var JOB_MODE = ostr(
|
|
53
|
+
"Fetch tier, and the price-bearing parameter: 'normal' is the standard fetch, 'advanced' renders JavaScript-built pages, 'ultra' reaches the hardest pages. Server default 'normal'."
|
|
54
|
+
);
|
|
55
|
+
var JOB_PATHS = "Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].";
|
|
56
|
+
var JOB_PRICE = "Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2 credits. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.";
|
|
57
|
+
var JOB_FORMAT = ostr("Format for each page, as on extract: 'html', 'markdown' or 'text' (server default 'markdown').");
|
|
58
|
+
var JOB_WAIT = onum(
|
|
59
|
+
"Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool."
|
|
60
|
+
);
|
|
61
|
+
var JOB_LIMIT = onum(
|
|
62
|
+
"Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor."
|
|
63
|
+
);
|
|
64
|
+
var JOB_INCLUDE_CONTENT = obool("Set false to list results without their page content (default true).");
|
|
65
|
+
var JOB_STATUS_PARAMS = z.object({
|
|
66
|
+
id: str("Job id returned when the job was started (data.id)."),
|
|
67
|
+
cursor: ostr("next_cursor from the previous response, to read the next page."),
|
|
68
|
+
limit: JOB_LIMIT,
|
|
69
|
+
status: ostr("Only results with this status: 'succeeded', 'failed' or 'skipped'."),
|
|
70
|
+
include_content: JOB_INCLUDE_CONTENT
|
|
71
|
+
});
|
|
25
72
|
function buildScavioToolkit(options = {}) {
|
|
26
73
|
const {
|
|
27
74
|
apiKey,
|
|
@@ -57,6 +104,8 @@ function buildScavioToolkit(options = {}) {
|
|
|
57
104
|
enableCapterra = false,
|
|
58
105
|
enableGoogleAds = false,
|
|
59
106
|
enableMetaAds = false,
|
|
107
|
+
enableCrawl = false,
|
|
108
|
+
pollIntervalMs = JOB_POLL_INTERVAL_MS,
|
|
60
109
|
all = false
|
|
61
110
|
} = options;
|
|
62
111
|
const client = new Scavio({ apiKey: apiKey ?? process.env.SCAVIO_API_KEY });
|
|
@@ -2406,15 +2455,101 @@ function buildScavioToolkit(options = {}) {
|
|
|
2406
2455
|
z.object({
|
|
2407
2456
|
url: str("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 with a 400."),
|
|
2408
2457
|
format: ostr("Output format: 'html' is the raw page, 'markdown' a readability extraction, 'text' that markdown flattened to plain text (server default 'markdown')."),
|
|
2409
|
-
mode: ostr("Fetch tier, and the price-bearing parameter: 'normal'
|
|
2458
|
+
mode: ostr("Fetch tier, and the price-bearing parameter: 'normal' is the standard fetch (1 credit), 'advanced' renders JavaScript-built pages (1 credit), 'ultra' reaches the hardest pages (2 credits). Server default 'normal'.")
|
|
2410
2459
|
}),
|
|
2411
2460
|
(i) => client.extract(i)
|
|
2412
2461
|
)
|
|
2413
2462
|
);
|
|
2414
2463
|
}
|
|
2464
|
+
if (all || enableCrawl) {
|
|
2465
|
+
const crawlStatus = (id, q) => client.extract.crawlStatus(id, q);
|
|
2466
|
+
const batchStatus = (id, q) => client.extract.batchStatus(id, q);
|
|
2467
|
+
const readStatus = (status) => async ({ id, limit, ...q }) => await status(id, {
|
|
2468
|
+
...q,
|
|
2469
|
+
limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT
|
|
2470
|
+
});
|
|
2471
|
+
tools.push(
|
|
2472
|
+
tool(
|
|
2473
|
+
"MAP_WEBSITE",
|
|
2474
|
+
"Scavio Map Website",
|
|
2475
|
+
"List a website's page URLs, gathered from its sitemaps and its start page, deduplicated, filtered by path or search words and limited: { url, links: [{ url, source, lastmod }], total_found, returned, truncated }. Pages the site's robots.txt disallows are left out. Use it to find the right pages before extracting or crawling. Costs 1 credit in normal mode; advanced costs up to 2 credits and ultra up to 10, priced by what the call needed.",
|
|
2476
|
+
z.object({
|
|
2477
|
+
url: str("The site to map. A bare host is upgraded to https."),
|
|
2478
|
+
search: ostr("Only return URLs containing every word of this text (case-insensitive)."),
|
|
2479
|
+
limit: onum("Maximum links to return, 1-5000. Default 1000 (or the plan's limit if lower: Free 500, PAYG 1,000, paid plans 5,000)."),
|
|
2480
|
+
sitemap: ostr("'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone."),
|
|
2481
|
+
include_subdomains: obool("Also return URLs on subdomains of the site (default false)."),
|
|
2482
|
+
include_paths: oarrstr("Keep only URLs matching these. " + JOB_PATHS),
|
|
2483
|
+
exclude_paths: oarrstr("Drop URLs matching these. " + JOB_PATHS),
|
|
2484
|
+
ignore_query_parameters: obool("Treat URLs that differ only by query string as one URL (default true)."),
|
|
2485
|
+
mode: JOB_MODE
|
|
2486
|
+
}),
|
|
2487
|
+
async (i) => await client.extract.map(i)
|
|
2488
|
+
),
|
|
2489
|
+
tool(
|
|
2490
|
+
"CRAWL_WEBSITE",
|
|
2491
|
+
"Scavio Crawl Website",
|
|
2492
|
+
"Crawl a website from one start URL: same-site pages are discovered and extracted breadth-first within the page, depth and path limits, each returned as Markdown, text or HTML. Pages the site's robots.txt disallows are skipped. Waits up to wait_seconds (default 45) and returns { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call LOCAL_SCAVIO_CRAWL_STATUS with the id later. " + JOB_PRICE,
|
|
2493
|
+
z.object({
|
|
2494
|
+
url: str("Where the crawl starts. Only pages on the same site are crawled."),
|
|
2495
|
+
max_pages: onum("Maximum pages to fetch. Default 100. Plan limits: Free 10, PAYG 100, Project 500, Bootstrap 2,000, Startup 5,000, Growth 10,000."),
|
|
2496
|
+
max_depth: onum("How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page."),
|
|
2497
|
+
include_paths: oarrstr("Crawl only paths matching these. " + JOB_PATHS),
|
|
2498
|
+
exclude_paths: oarrstr("Skip paths matching these. " + JOB_PATHS),
|
|
2499
|
+
allow_subdomains: obool("Also crawl subdomains of the site (default false)."),
|
|
2500
|
+
ignore_query_parameters: obool("Treat URLs that differ only by query string as one page (default true)."),
|
|
2501
|
+
sitemap: ostr("'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links."),
|
|
2502
|
+
format: JOB_FORMAT,
|
|
2503
|
+
mode: JOB_MODE,
|
|
2504
|
+
wait_seconds: JOB_WAIT,
|
|
2505
|
+
limit: JOB_LIMIT,
|
|
2506
|
+
include_content: JOB_INCLUDE_CONTENT
|
|
2507
|
+
}),
|
|
2508
|
+
(i) => startAndWait(
|
|
2509
|
+
(body) => client.extract.crawl(body),
|
|
2510
|
+
crawlStatus,
|
|
2511
|
+
i,
|
|
2512
|
+
pollIntervalMs
|
|
2513
|
+
)
|
|
2514
|
+
),
|
|
2515
|
+
tool(
|
|
2516
|
+
"CRAWL_STATUS",
|
|
2517
|
+
"Scavio Crawl Status",
|
|
2518
|
+
"Read a crawl's progress and its page results by job id, paged by cursor: { status, stopped_reason, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the crawl finishes. Free: reading a job costs no credits.",
|
|
2519
|
+
JOB_STATUS_PARAMS,
|
|
2520
|
+
readStatus(crawlStatus)
|
|
2521
|
+
),
|
|
2522
|
+
tool(
|
|
2523
|
+
"BATCH_EXTRACT",
|
|
2524
|
+
"Scavio Batch Extract",
|
|
2525
|
+
"Extract a list of URLs (up to 1,000, plan-limited) in one job, each returned as Markdown, text or HTML exactly like LOCAL_SCAVIO_EXTRACT. Waits up to wait_seconds (default 45) and returns { id, status, pages, credits_used, results, next_cursor }; if status is still queued or running, call LOCAL_SCAVIO_BATCH_STATUS with the id later. " + JOB_PRICE,
|
|
2526
|
+
z.object({
|
|
2527
|
+
urls: arrstr("The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000."),
|
|
2528
|
+
format: JOB_FORMAT,
|
|
2529
|
+
mode: JOB_MODE,
|
|
2530
|
+
wait_seconds: JOB_WAIT,
|
|
2531
|
+
limit: JOB_LIMIT,
|
|
2532
|
+
include_content: JOB_INCLUDE_CONTENT
|
|
2533
|
+
}),
|
|
2534
|
+
(i) => startAndWait(
|
|
2535
|
+
(body) => client.extract.batch(body),
|
|
2536
|
+
batchStatus,
|
|
2537
|
+
i,
|
|
2538
|
+
pollIntervalMs
|
|
2539
|
+
)
|
|
2540
|
+
),
|
|
2541
|
+
tool(
|
|
2542
|
+
"BATCH_STATUS",
|
|
2543
|
+
"Scavio Batch Status",
|
|
2544
|
+
"Read a batch extract's progress and its page results by job id, paged by cursor: { status, pages, credits_used, results: [{ url, status, content }], next_cursor }. Results are kept for 3 days after the batch finishes. Free: reading a job costs no credits.",
|
|
2545
|
+
JOB_STATUS_PARAMS,
|
|
2546
|
+
readStatus(batchStatus)
|
|
2547
|
+
)
|
|
2548
|
+
);
|
|
2549
|
+
}
|
|
2415
2550
|
return experimental_createToolkit("SCAVIO", {
|
|
2416
2551
|
name: "Scavio",
|
|
2417
|
-
description: "Real-time structured search over
|
|
2552
|
+
description: "Real-time structured search over 31 platforms - Google (SERP, AI Mode, Maps, Shopping, Flights, Hotels, News, Trends), YouTube, Amazon, Walmart, eBay, Target, Home Depot, Reddit, TikTok, TikTok Shop, Instagram, X, LinkedIn, Threads, Kuaishou, Zillow, Redfin, Booking.com, Airbnb, Tripadvisor, Yelp, Indeed, Glassdoor, the Apple App Store, Google Play, SEC EDGAR, Companies House, G2, Capterra, Google Ads Transparency and the Meta Ad Library - plus extract, which reads any URL as Markdown, plain text or raw HTML, and website map, crawl and batch extract.",
|
|
2418
2553
|
tools
|
|
2419
2554
|
});
|
|
2420
2555
|
}
|