composio-scavio 0.5.0 → 0.5.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Scavio tools for Composio.\n *\n * Scavio is a single Search API over 31 platforms - Google, YouTube, Amazon,\n * Walmart, eBay, Target, Home Depot, Reddit, TikTok, TikTok Shop, Instagram, X,\n * LinkedIn, Threads, Kuaishou, Zillow, Redfin, Booking.com, Airbnb, Tripadvisor,\n * Yelp, Indeed, Glassdoor, the Apple App Store, Google Play, SEC EDGAR, Companies\n * House, G2, Capterra, Google Ads Transparency and the Meta Ad Library - plus a\n * top-level extract() that reads any URL as Markdown, plain text or raw HTML.\n * This toolkit exposes every live endpoint of all of them (189 tools), plus five\n * opt-in website tools (map, crawl, batch) behind enableCrawl. Build it\n * with `buildScavioToolkit()` and bind it to a session:\n *\n * import { Composio } from \"@composio/core\";\n * import { buildScavioToolkit } from \"composio-scavio\";\n *\n * const composio = new Composio();\n * const scavio = buildScavioToolkit({ apiKey: process.env.SCAVIO_API_KEY });\n * const session = await composio.create(\"user_1\", {\n * experimental: { customToolkits: [scavio] },\n * });\n * const out = await session.execute(\"LOCAL_SCAVIO_GOOGLE_SEARCH\", { query: \"ai agents\" });\n *\n * Each provider is gated by an `enable*` flag so an agent only sees the tools it\n * needs. The ten original platforms and `extract` are on by default (104 tools);\n * the 21 verticals added in 0.4.0 are OPT-IN, because registering all 189 at once\n * buries the handful an agent actually wants. Pass `all: true` for everything.\n */\nimport {\n experimental_createTool,\n experimental_createToolkit,\n} from \"@composio/core\";\nimport { Scavio } from \"scavio\";\nimport { z } from \"zod\";\n\nexport interface BuildScavioToolkitOptions {\n /** Scavio API key. Falls back to the SCAVIO_API_KEY env var. */\n apiKey?: string;\n enableGoogle?: boolean;\n enableAmazon?: boolean;\n enableWalmart?: boolean;\n enableYoutube?: boolean;\n enableReddit?: boolean;\n enableTiktok?: boolean;\n enableTiktokShop?: boolean;\n enableInstagram?: boolean;\n enableX?: boolean;\n enableLinkedin?: boolean;\n /** The top-level extract() tool: read any URL as Markdown, text or HTML. */\n enableExtract?: boolean;\n // Added in 0.4.0. Opt-in: off unless you ask for them, or pass all.\n enableThreads?: boolean;\n enableKuaishou?: boolean;\n enableEbay?: boolean;\n enableTarget?: boolean;\n enableHomeDepot?: boolean;\n enableZillow?: boolean;\n enableBooking?: boolean;\n enableTripadvisor?: boolean;\n enableIndeed?: boolean;\n enableAirbnb?: boolean;\n enableGlassdoor?: boolean;\n enableYelp?: boolean;\n enableAppStore?: boolean;\n enableGooglePlay?: boolean;\n enableSec?: boolean;\n enableRedfin?: boolean;\n enableCompaniesHouse?: boolean;\n enableG2?: boolean;\n enableCapterra?: boolean;\n enableGoogleAds?: boolean;\n enableMetaAds?: boolean;\n /**\n * Website map, crawl and batch extract (five tools: MAP_WEBSITE, CRAWL_WEBSITE,\n * CRAWL_STATUS, BATCH_EXTRACT, BATCH_STATUS). Opt-in: a crawl bills per page.\n */\n enableCrawl?: boolean;\n /**\n * Milliseconds between progress polls while CRAWL_WEBSITE or BATCH_EXTRACT\n * waits for its job. Default 3000.\n */\n pollIntervalMs?: number;\n /** Register every tool, ignoring the individual flags. */\n all?: boolean;\n}\n\nconst str = (d: string) => z.string().describe(d);\nconst ostr = (d: string) => z.string().optional().describe(d);\nconst onum = (d: string) => z.number().optional().describe(d);\nconst obool = (d: string) => z.boolean().optional().describe(d);\nconst arrstr = (d: string) => z.array(z.string()).describe(d);\nconst oarrstr = (d: string) => z.array(z.string()).optional().describe(d);\nconst oarrnum = (d: string) => z.array(z.number()).optional().describe(d);\n// Booking's property_type is a named enum OR a raw numeric accommodation-type id.\nconst ostrnum = (d: string) => z.union([z.string(), z.number()]).optional().describe(d);\n// SEC filters take a single value, a list, or the comma-joined string.\nconst ostrarr = (d: string) =>\n z.union([z.string(), z.array(z.string())]).optional().describe(d);\n\n// The Scavio SDK types several option fields as string-literal unions (e.g.\n// sort orders, device profiles). Tool schemas keep them as free-form strings so\n// the agent stays flexible and the API validates the value; this extracts an SDK\n// method's options type so a validated input can be handed through unchanged.\ntype SdkOpts<M> = M extends (o: infer O) => unknown ? O : never;\n\n// Google params shared across the v2 family. v1 (/api/v1/google) was retired on\n// 2026-08-04 and answers 410, so none of its vocabulary survives here: no\n// country_code/language/page, no light_request, no search_type. v2 speaks\n// gl/hl/start/google_domain/device natively and they are exposed as-is. `start`\n// in particular is a RESULT OFFSET, not a page number - remapping a 1-based page\n// onto it silently fetches the wrong page, so no such mapping exists.\nconst gl = ostr(\"Country of the search (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de').\");\nconst hl = ostr(\"UI language (ISO 639-1, e.g. 'en').\");\nconst googleDomain = ostr(\"Regional Google domain, e.g. 'google.co.uk'.\");\nconst location = ostr(\"Canonical location name, e.g. 'Austin, Texas, United States'. Encoded server-side.\");\nconst device = ostr(\"Device to emulate: 'desktop' or 'mobile'.\");\nconst currency = ostr(\"Currency code (ISO 4217, e.g. 'USD').\");\nconst checkInDate = str(\"Check-in date (YYYY-MM-DD).\");\nconst checkOutDate = str(\"Check-out date (YYYY-MM-DD).\");\n\n// Website map, crawl and batch: the multi-page members of the Extract family.\n//\n// Map answers in one call. Crawl and batch are background jobs: the start tools\n// post the job, then wait up to wait_seconds (default 45, max 300) for it to\n// finish, polling progress without page content, and return the job's status\n// with its first page of results either way. A job still running when the wait\n// ends keeps going server-side; read the rest with the matching status tool.\n// Cancellation, webhooks and idempotency keys are in the SDK, not tools.\nconst JOB_POLL_INTERVAL_MS = 3_000;\nconst JOB_WAIT_DEFAULT_SECONDS = 45;\nconst JOB_WAIT_MAX_SECONDS = 300;\nconst JOB_RESULTS_DEFAULT_LIMIT = 10;\nconst JOB_TERMINAL = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\ntype JobQuery = {\n cursor?: string;\n limit?: number;\n status?: \"succeeded\" | \"failed\" | \"skipped\";\n include_content?: boolean;\n};\ntype JobPayload = { data?: { id?: string; status?: string } } & Record<string, unknown>;\ntype JobStatusFn = (id: string, query: JobQuery) => Promise<unknown>;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** Poll a job (content-free) until it finishes or the wait runs out, then read one results page. */\nasync function waitForJob(\n status: JobStatusFn,\n id: string,\n waitSeconds: number,\n pollMs: number,\n query: JobQuery\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1000;\n for (;;) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollMs, remaining));\n const probe = (await status(id, { limit: 1, include_content: false })) as JobPayload;\n if (JOB_TERMINAL.has(String(probe?.data?.status))) break;\n }\n return (await status(id, query)) as Record<string, unknown>;\n}\n\n/** Start a job, then wait for it (bounded). wait_seconds 0 returns the 202 payload. */\nasync function startAndWait(\n start: (body: Record<string, unknown>) => Promise<unknown>,\n status: JobStatusFn,\n input: Record<string, unknown>,\n pollMs: number\n): Promise<Record<string, unknown>> {\n const { wait_seconds, limit, include_content, ...body } = input as Record<string, unknown> & {\n wait_seconds?: number;\n limit?: number;\n include_content?: boolean;\n };\n const created = (await start(body)) as JobPayload;\n const id = created?.data?.id;\n const wait = wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;\n if (!id || wait <= 0) return created;\n const query: JobQuery = { limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT };\n if (include_content !== undefined) query.include_content = include_content;\n return waitForJob(status, id, wait, pollMs, query);\n}\n\nconst JOB_MODE = ostr(\n \"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'.\"\n);\nconst JOB_PATHS =\n \"Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].\";\nconst JOB_PRICE =\n \"Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2 credits. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.\";\nconst JOB_FORMAT = ostr(\"Format for each page, as on extract: 'html', 'markdown' or 'text' (server default 'markdown').\");\nconst JOB_WAIT = onum(\n \"Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool.\"\n);\nconst JOB_LIMIT = onum(\n \"Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor.\"\n);\nconst JOB_INCLUDE_CONTENT = obool(\"Set false to list results without their page content (default true).\");\nconst JOB_STATUS_PARAMS = z.object({\n id: str(\"Job id returned when the job was started (data.id).\"),\n cursor: ostr(\"next_cursor from the previous response, to read the next page.\"),\n limit: JOB_LIMIT,\n status: ostr(\"Only results with this status: 'succeeded', 'failed' or 'skipped'.\"),\n include_content: JOB_INCLUDE_CONTENT,\n});\n\n/**\n * Build a Composio custom toolkit exposing Scavio search tools.\n *\n * Scavio is a single Search API over Google, YouTube, Amazon, Walmart, Reddit,\n * TikTok, TikTok Shop, Instagram, X and LinkedIn; this toolkit covers all ten.\n * Pass to `composio.create(userId, { experimental:\n * { customToolkits: [toolkit] } })`. Agent-facing slugs are prefixed `LOCAL_SCAVIO_`.\n */\nexport function buildScavioToolkit(options: BuildScavioToolkitOptions = {}) {\n const {\n apiKey,\n enableGoogle = true,\n enableAmazon = true,\n enableWalmart = true,\n enableYoutube = true,\n enableReddit = true,\n enableTiktok = true,\n enableTiktokShop = true,\n enableInstagram = true,\n enableX = true,\n enableLinkedin = true,\n enableExtract = true,\n enableThreads = false,\n enableKuaishou = false,\n enableEbay = false,\n enableTarget = false,\n enableHomeDepot = false,\n enableZillow = false,\n enableBooking = false,\n enableTripadvisor = false,\n enableIndeed = false,\n enableAirbnb = false,\n enableGlassdoor = false,\n enableYelp = false,\n enableAppStore = false,\n enableGooglePlay = false,\n enableSec = false,\n enableRedfin = false,\n enableCompaniesHouse = false,\n enableG2 = false,\n enableCapterra = false,\n enableGoogleAds = false,\n enableMetaAds = false,\n enableCrawl = false,\n pollIntervalMs = JOB_POLL_INTERVAL_MS,\n all = false,\n } = options;\n\n const client = new Scavio({ apiKey: apiKey ?? process.env.SCAVIO_API_KEY });\n\n function tool<T extends z.ZodTypeAny>(\n slug: string,\n name: string,\n description: string,\n inputParams: T,\n call: (input: z.infer<T>) => Promise<Record<string, unknown>>\n ) {\n return experimental_createTool(slug, {\n name,\n description,\n inputParams,\n execute: async (input: z.infer<T>) => call(input),\n });\n }\n\n const tools = [];\n\n // Google runs on /api/v2/google. Responses are FLAT - the provider payload is\n // spread at the top level next to response_time and credits_used, with no\n // `data` wrapper. All 14 endpoints cost 1 credit.\n if (all || enableGoogle) {\n tools.push(\n tool(\n \"GOOGLE_SEARCH\",\n \"Scavio Google Search\",\n \"Search Google for real-time web results. Returns organic_results (each with title, link and snippet) plus knowledge_graph, related_questions, ads and the AI Overview when Google shows one. The body is flat - read organic_results at the top level, not under data. Costs 1 credit.\",\n z.object({\n query: str(\"The search query (1-500 characters).\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n start: onum(\"Result offset, NOT a page number: 0 is page 1, 10 is page 2, up to 990.\"),\n time_period: ostr(\"Restrict results to a recent time window: 'last_hour', 'last_day', 'last_week', 'last_month', or 'last_year'.\"),\n safe: ostr(\"Turn SafeSearch on with 'active'.\"),\n nfpr: obool(\"Disable spelling correction and auto-fixes when true.\"),\n }),\n (i) => client.google.search(i as SdkOpts<typeof client.google.search>)\n ),\n tool(\n \"GOOGLE_AI_MODE\",\n \"Scavio Google AI Mode\",\n \"Ask Google AI Mode a question. Returns Google's generated answer with its cited sources - use this for a synthesized answer and GOOGLE_SEARCH for a ranked result list. Costs 1 credit.\",\n z.object({\n query: str(\"Question or prompt (1-500 characters).\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n safe: ostr(\"Turn SafeSearch on with 'active'.\"),\n }),\n (i) => client.google.aiMode(i as SdkOpts<typeof client.google.aiMode>)\n ),\n tool(\n \"GOOGLE_MAPS_SEARCH\",\n \"Scavio Google Maps Search\",\n \"Search Google Maps for local businesses and places. Returns local results with ratings, review counts, addresses, phone numbers and place ids. Feed a place_id into GOOGLE_MAPS_PLACE or GOOGLE_MAPS_REVIEWS. Costs 1 credit.\",\n z.object({\n query: str(\"Search query, e.g. 'coffee shops in Austin' (1-500 characters).\"),\n ll: ostr(\"Map centre as '@lat,lng,zoomz'; controls which area results come from. Maps localizes by map centre, not gl.\"),\n start: onum(\"Result offset; must be a multiple of 20 (0, 20, 40, ...).\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.mapsSearch(i)\n ),\n tool(\n \"GOOGLE_MAPS_PLACE\",\n \"Scavio Google Maps Place\",\n \"Fetch one Google Maps place in full: hours, address, phone, website, rating, price level and photos. Provide place_id or data_cid. Costs 1 credit.\",\n z.object({\n place_id: ostr(\"Place ID (starts with ChIJ). Provide this or data_cid.\"),\n data_cid: ostr(\"Numeric CID. Provide this or place_id.\"),\n }),\n (i) => client.google.mapsPlace(i)\n ),\n tool(\n \"GOOGLE_MAPS_REVIEWS\",\n \"Scavio Google Maps Reviews\",\n \"List Google Maps reviews for a place. Provide data_id or place_id. Page with next_page_token; each page costs another credit. Costs 1 credit.\",\n z.object({\n place_id: ostr(\"Place ID (starts with ChIJ). Provide this or data_id.\"),\n data_id: ostr(\"Data ID in 0xHEX:0xHEX form. Provide this or place_id.\"),\n num: onum(\"Reviews per page (1-20).\"),\n sort_by: ostr(\"Review sort order: 'relevance', 'newest', 'highest_rating', or 'lowest_rating'.\"),\n next_page_token: ostr(\"Pagination cursor from a prior response.\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.mapsReviews(i as SdkOpts<typeof client.google.mapsReviews>)\n ),\n tool(\n \"GOOGLE_SHOPPING\",\n \"Scavio Google Shopping\",\n \"Search Google Shopping. Returns product cards with prices, merchants, ratings and catalog ids across retailers - use this for cross-retailer price comparison and AMAZON_SEARCH or WALMART_SEARCH for a single marketplace. Costs 1 credit.\",\n z.object({\n query: str(\"Product search query (1-500 characters).\"),\n min_price: onum(\"Minimum price filter.\"),\n max_price: onum(\"Maximum price filter.\"),\n sort_by: onum(\"0 = relevance, 1 = price ascending, 2 = price descending.\"),\n free_shipping: obool(\"Only items with free shipping.\"),\n on_sale: obool(\"Only items on sale.\"),\n start: onum(\"Result offset.\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n }),\n (i) => client.google.shopping(i as SdkOpts<typeof client.google.shopping>)\n ),\n tool(\n \"GOOGLE_SHOPPING_PRODUCT\",\n \"Scavio Google Shopping Product\",\n \"Fetch one Google Shopping product: specs, reviews, and the sellers carrying it. Pass catalog_id together with query for full detail and the seller list. Costs 1 credit.\",\n z.object({\n catalog_id: ostr(\"Durable product catalog id from a shopping search.\"),\n query: ostr(\"Product query. Required when catalog_id is set.\"),\n product_id: ostr(\"Product id, as an alternative to catalog_id.\"),\n page_token: ostr(\"Immersive product page token.\"),\n sort_by: ostr(\"Seller sort order: 'base_price', 'total_price', 'promotion', or 'seller_rating'.\"),\n load_all_stores: obool(\"Load every available store.\"),\n more_stores: obool(\"Fetch additional stores.\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device: ostr(\"Device to emulate: 'desktop', 'mobile', or 'tablet'.\"),\n }),\n (i) => client.google.shoppingProduct(i as SdkOpts<typeof client.google.shoppingProduct>)\n ),\n tool(\n \"GOOGLE_SHOPPING_STORES\",\n \"Scavio Google Shopping Stores\",\n \"Fetch the next page of sellers for a Google Shopping product. Continuation of GOOGLE_SHOPPING_PRODUCT: pass the same catalog_id plus that response's next_page_token. Costs 1 credit.\",\n z.object({\n catalog_id: str(\"Durable product catalog id.\"),\n next_page_token: str(\"Pagination cursor from GOOGLE_SHOPPING_PRODUCT.\"),\n }),\n (i) => client.google.shoppingStores(i)\n ),\n tool(\n \"GOOGLE_FLIGHTS\",\n \"Scavio Google Flights\",\n \"Search Google Flights. Returns itineraries with prices, airlines, stops, durations and carbon emissions. Airports are IATA codes; dates are YYYY-MM-DD. Costs 1 credit.\",\n z.object({\n departure_id: str(\"Departure IATA code(s), comma-separated allowed, e.g. 'JFK'.\"),\n arrival_id: str(\"Arrival IATA code(s), comma-separated allowed, e.g. 'LHR'.\"),\n outbound_date: str(\"Outbound date (YYYY-MM-DD).\"),\n return_date: ostr(\"Return date (YYYY-MM-DD). Required when type is 1.\"),\n type: onum(\"1 = round trip (default), 2 = one way, 3 = multi-city.\"),\n adults: onum(\"Number of adults (1-9).\"),\n children: onum(\"Number of children (0-9).\"),\n infants_in_seat: onum(\"Infants in seat (0-4).\"),\n infants_on_lap: onum(\"Infants on lap (0-4).\"),\n travel_class: onum(\"1 = economy, 2 = premium economy, 3 = business, 4 = first.\"),\n stops: onum(\"0 = any, 1 = nonstop, 2 = one stop or fewer, 3 = two or fewer.\"),\n sort_by: onum(\"1 = top, 2 = price, 3 = departure, 4 = arrival, 5 = duration, 6 = emissions.\"),\n include_airlines: ostr(\"Comma-separated airline or alliance codes to include.\"),\n exclude_airlines: ostr(\"Comma-separated airline or alliance codes to exclude.\"),\n currency,\n gl,\n hl,\n }),\n (i) => client.google.flights(i)\n ),\n tool(\n \"GOOGLE_HOTELS\",\n \"Scavio Google Hotels\",\n \"Search Google Hotels. Returns properties with nightly prices, ratings, amenities and a detail_token for GOOGLE_HOTELS_DETAIL. Phrase the query as '<City> hotels'. Costs 1 credit.\",\n z.object({\n query: str(\"Search query; use a '<City> hotels' form.\"),\n check_in_date: checkInDate,\n check_out_date: checkOutDate,\n sort_by: onum(\"3 = lowest price, 8 = highest rating, 13 = most reviewed.\"),\n min_price: onum(\"Minimum nightly price.\"),\n max_price: onum(\"Maximum nightly price.\"),\n rating: onum(\"7 = 3.5+, 8 = 4.0+, 9 = 4.5+.\"),\n hotel_class: ostr(\"Comma-separated star ratings (2-5).\"),\n amenities: ostr(\"Comma-separated amenity ids.\"),\n property_types: ostr(\"Comma-separated property-type ids, e.g. '12' for vacation rentals.\"),\n free_cancellation: obool(\"Only properties with free cancellation.\"),\n eco_certified: obool(\"Only eco-certified properties.\"),\n special_offers: obool(\"Only properties with special offers.\"),\n limit: onum(\"Number of properties to return (1-20).\"),\n next_page_token: ostr(\"Pagination cursor from a prior response.\"),\n currency,\n gl,\n hl,\n }),\n (i) => client.google.hotels(i)\n ),\n tool(\n \"GOOGLE_HOTELS_DETAIL\",\n \"Scavio Google Hotels Detail\",\n \"Fetch one Google Hotels property in full: room types, per-night prices by provider, amenities, photos and reviews. Needs a detail_token from GOOGLE_HOTELS and the same stay dates. Costs 1 credit.\",\n z.object({\n detail_token: str(\"Property detail token from a hotels listing.\"),\n check_in_date: checkInDate,\n check_out_date: checkOutDate,\n currency,\n gl,\n hl,\n }),\n (i) => client.google.hotelsDetail(i)\n ),\n tool(\n \"GOOGLE_NEWS\",\n \"Scavio Google News\",\n \"Fetch Google News. Pass query to search, or a topic_token / story_token / publication_token from an earlier response to browse a topic, a full story or one publisher. Costs 1 credit.\",\n z.object({\n query: ostr(\"Keyword search.\"),\n topic_token: ostr(\"Browse a news topic.\"),\n section_token: ostr(\"Browse a topic section.\"),\n story_token: ostr(\"Fetch full coverage of one story.\"),\n publication_token: ostr(\"Browse one publication.\"),\n kgmid: ostr(\"Knowledge Graph entity id.\"),\n so: onum(\"Sort: 0 = relevance, 1 = date. Only applies with query or kgmid.\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.news(i)\n ),\n tool(\n \"GOOGLE_TRENDS\",\n \"Scavio Google Trends\",\n \"Fetch Google Trends interest data. Comma-separate the query to compare terms, and pick the dataset with data_type: TIMESERIES for interest over time, GEO_MAP for interest by region, RELATED_QUERIES or RELATED_TOPICS for rising searches. Costs 1 credit.\",\n z.object({\n query: str(\"Search term(s); comma-separated to compare up to five.\"),\n data_type: ostr(\"Which trends dataset to return: 'TIMESERIES', 'GEO_MAP', 'GEO_MAP_0', 'RELATED_QUERIES', or 'RELATED_TOPICS'.\"),\n geo: ostr(\"Location code, e.g. 'US', 'GB', 'US-CA'. Omit for worldwide.\"),\n date: ostr(\"Time range, e.g. 'today 12-m', 'now 7-d'.\"),\n cat: ostr(\"Category id.\"),\n gprop: ostr(\"Restrict to a Google property: 'images', 'news', 'youtube', or 'froogle'.\"),\n region: ostr(\"Resolution for GEO_MAP data: 'COUNTRY', 'REGION', 'DMA', or 'CITY'.\"),\n tz: ostr(\"Timezone offset in minutes.\"),\n hl,\n }),\n (i) => client.google.trends(i as SdkOpts<typeof client.google.trends>)\n ),\n tool(\n \"GOOGLE_TRENDING\",\n \"Scavio Google Trending\",\n \"List what is trending on Google right now for one country. geo is required. Use GOOGLE_TRENDS instead when you already know the term you care about. Costs 1 credit.\",\n z.object({\n geo: str(\"Country code, e.g. 'US'.\"),\n hours: onum(\"Trending window in hours: 4, 24, 48 or 168.\"),\n cat: onum(\"Category id (0-20).\"),\n sort: ostr(\"Sort order: 'relevance', 'search_volume', 'recency', or 'title'.\"),\n status: ostr(\"Filter by trend status: 'all' or 'active'.\"),\n hl,\n }),\n (i) => client.google.trending(i as SdkOpts<typeof client.google.trending>)\n )\n );\n }\n\n // Amazon moved upstream in 2026-07: sort_by, pages, category_id, merchant_id,\n // language, currency, device, zip_code and autoselect_variant no longer exist.\n // Removed rather than kept as no-ops - sort_by was verified to return the\n // identical unordered set for every value. `domain` still works on the wire\n // as a deprecated alias but is not offered: one spelling per param.\n if (all || enableAmazon) {\n tools.push(\n tool(\n \"AMAZON_SEARCH\",\n \"Scavio Amazon Search\",\n \"Search Amazon for products matching a query. Results are unsorted and cannot be filtered by category, merchant or price. Costs 1 credit.\",\n z.object({\n query: str(\"The product search query.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n page: onum(\"Result page, 1-based. One page per call, 1 credit each.\"),\n }),\n (i) => client.amazon.search(i as SdkOpts<typeof client.amazon.search>)\n ),\n tool(\n \"AMAZON_PRODUCT\",\n \"Scavio Amazon Product\",\n \"Fetch full Amazon product details by ASIN. price is the buy-box price only. Costs 1 credit.\",\n z.object({\n asin: str(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n }),\n (i) => client.amazon.product(i as SdkOpts<typeof client.amazon.product>)\n ),\n tool(\n \"AMAZON_OFFERS\",\n \"Scavio Amazon Offers\",\n \"List every seller offer for one Amazon ASIN: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only. Use this instead of AMAZON_PRODUCT when comparing sellers or checking who owns the buy box. Costs 1 credit.\",\n z.object({\n asin: str(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n }),\n (i) => client.amazon.offers(i as SdkOpts<typeof client.amazon.offers>)\n ),\n tool(\n \"AMAZON_OPTIONS\",\n \"Scavio Amazon Options\",\n \"Supported Amazon marketplaces, as 'domains' and 'countries'. 'languages' and 'currencies' remain in the payload but are always empty: neither is a request param any more. Needs no API key and costs no credits.\",\n z.object({}),\n () => client.amazon.options()\n )\n );\n }\n\n // Walmart was rebuilt: device, delivery_zip and store_id\n // never existed on it, start_page is now page, and it is BODY-PRICED - 1 credit\n // on domain com/ca, 2 on com.mx, so search and category alone carry a domain.\n if (all || enableWalmart) {\n tools.push(\n tool(\n \"WALMART_SEARCH\",\n \"Scavio Walmart Search\",\n \"Search Walmart and get structured product rows (products, products_count and the store the results were priced against). Costs 1 credit on domain 'com' or 'ca' and 2 credits on 'com.mx' - the price is a function of the request body, not a constant for the route.\",\n z.object({\n query: str(\"Product search query (1-500 characters).\"),\n domain: ostr(\"Marketplace: 'com' (US, default, 1 credit), 'ca' (1 credit), 'com.mx' (2 credits). Sets the currency and product URLs of the response.\"),\n page: onum(\"Results page, 1-based (integer >= 1). One page per call.\"),\n start_page: onum(\"Deprecated alias for page; send page instead.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Accepted values: 'best_match', 'price_low', 'price_high', 'best_seller', 'rating_high', 'new'.\"),\n min_price: onum(\"Minimum price filter in the marketplace's own currency; decimals allowed (e.g. 19.99).\"),\n max_price: onum(\"Maximum price filter in the marketplace's own currency; decimals allowed (e.g. 199.5).\"),\n fulfillment_speed: ostr(\"Only items deliverable today, or by tomorrow. '2_days' and 'anytime' are not accepted - for anytime, omit this parameter.\"),\n fulfillment_type: ostr(\"Set to 'in_store' to return only items available for in-store pickup.\"),\n }),\n (i) => client.walmart.search(i as SdkOpts<typeof client.walmart.search>)\n ),\n tool(\n \"WALMART_PRODUCT\",\n \"Scavio Walmart Product\",\n \"Full detail for a single Walmart product: price, rating, images, specifications, availability and seller. US marketplace only - walmart.ca product pages could not be fetched at all, so this endpoint takes no domain. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '13544111159'.\"),\n }),\n (i) => client.walmart.product(i as SdkOpts<typeof client.walmart.product>)\n ),\n tool(\n \"WALMART_REVIEWS\",\n \"Scavio Walmart Reviews\",\n \"Customer reviews for a Walmart product with ratings, text, author, date and the rating breakdown. 10 reviews per page; paginate with page. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '13544111159'.\"),\n page: onum(\"Reviews page, 1-based (integer >= 1). 10 reviews per page.\"),\n sort: ostr(\"Review sort order. Omit for Walmart's own default ordering. Accepted values: 'relevancy', 'submission-desc', 'submission-asc', 'rating-desc', 'rating-asc', 'helpful-desc'.\"),\n }),\n (i) => client.walmart.reviews(i as SdkOpts<typeof client.walmart.reviews>)\n ),\n tool(\n \"WALMART_CATEGORY\",\n \"Scavio Walmart Category\",\n \"Products within a Walmart category, in the same product shape as search. Costs 1 credit on domain 'com' or 'ca' and 2 credits on 'com.mx' - the price is a function of the request body, not a constant for the route.\",\n z.object({\n category_id: str(\"Walmart category id: either a leaf id ('1095191') or the full underscore-joined path ('3944_133251_1095191'). Both are accepted.\"),\n domain: ostr(\"Marketplace: 'com' (US, default, 1 credit), 'ca' (1 credit), 'com.mx' (2 credits). Sets the currency and product URLs of the response.\"),\n page: onum(\"Results page, 1-based (integer >= 1). One page per call.\"),\n limit: onum(\"Trim the returned products to at most this many (integer >= 1). Applied after fetching, so it does not reduce the credit cost of the call.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Accepted values: 'best_match', 'price_low', 'price_high', 'best_seller', 'rating_high', 'new'.\"),\n min_price: onum(\"Minimum price filter in the marketplace's own currency; decimals allowed (e.g. 19.99).\"),\n max_price: onum(\"Maximum price filter in the marketplace's own currency; decimals allowed (e.g. 199.5).\"),\n fulfillment_speed: ostr(\"Only items deliverable today, or by tomorrow. '2_days' and 'anytime' are not accepted - for anytime, omit this parameter.\"),\n }),\n (i) => client.walmart.category(i as SdkOpts<typeof client.walmart.category>)\n ),\n tool(\n \"WALMART_OFFERS\",\n \"Scavio Walmart Offers\",\n \"The buy-box offer for a Walmart product: price, seller, condition and buy-box flag. BUY-BOX SELLER ONLY - this is not the full offer list, and there is no way to page through the other sellers. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '2979510112'.\"),\n }),\n (i) => client.walmart.offers(i as SdkOpts<typeof client.walmart.offers>)\n ),\n tool(\n \"WALMART_SELLER\",\n \"Scavio Walmart Seller\",\n \"Marketplace seller storefront: name, rating, review count, Pro Seller badge and business details. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n seller_id: str(\"Numeric Walmart catalog seller id, as returned in `seller_catalog_id` on a product, search or offers response (e.g. '101480084'). The GUID `seller_id` is not accepted here - it 404s.\"),\n }),\n (i) => client.walmart.seller(i as SdkOpts<typeof client.walmart.seller>)\n ),\n tool(\n \"WALMART_SELLER_PRODUCTS\",\n \"Scavio Walmart Seller Products\",\n \"A marketplace seller's catalog. Roughly the first 40 items are server-rendered and returned; total_count reports the seller's real catalog size. There is no pagination - the rest of the catalog is not reachable. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n seller_id: str(\"Numeric Walmart catalog seller id, as returned in `seller_catalog_id` on a product, search or offers response (e.g. '101480084'). The GUID `seller_id` 404s.\"),\n }),\n (i) => client.walmart.sellerProducts(i as SdkOpts<typeof client.walmart.sellerProducts>)\n )\n );\n }\n\n // /youtube/metadata is a deprecated alias of /youtube/video and is deliberately\n // not exposed - two tools for one endpoint only makes an agent pick wrong.\n if (all || enableYoutube) {\n tools.push(\n tool(\n \"YOUTUBE_SEARCH\",\n \"Scavio YouTube Search\",\n \"Search YouTube for videos, channels, or playlists. Costs 2 credits.\",\n z.object({\n query: str(\"The video search query.\"),\n upload_date: ostr(\"Upload date filter: 'last_hour', 'today', 'this_week', 'this_month', 'this_year'.\"),\n type: ostr(\"Result type: 'video', 'channel', 'playlist', or 'movie'.\"),\n duration: ostr(\"Duration filter: 'short', 'medium', or 'long'.\"),\n sort_by: ostr(\"Sort order: 'relevance', 'date', 'view_count', or 'rating'.\"),\n features: z.array(z.string()).optional().describe(\"Feature filters, e.g. ['hd', '4k', 'subtitles', 'creative_commons', 'live', '360', '3d', 'hdr', 'vr180'].\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n hd: obool(\"Restrict to HD videos when true.\"),\n subtitles: obool(\"Restrict to videos with subtitles when true.\"),\n creative_commons: obool(\"Restrict to Creative Commons videos when true.\"),\n live: obool(\"Restrict to live videos when true.\"),\n }),\n (i) => client.youtube.search(i as SdkOpts<typeof client.youtube.search>)\n ),\n tool(\n \"YOUTUBE_SHORTS\",\n \"Scavio YouTube Shorts\",\n \"Search YouTube Shorts. Costs 2 credits.\",\n z.object({\n query: str(\"The Shorts search query.\"),\n sort_by: ostr(\"Sort order: 'relevance', 'date', 'view_count', or 'rating'.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.shorts(i as SdkOpts<typeof client.youtube.shorts>)\n ),\n tool(\n \"YOUTUBE_SUGGESTIONS\",\n \"Scavio YouTube Suggestions\",\n \"Get YouTube search autocomplete suggestions for a partial query. Costs 1 credit.\",\n z.object({\n query: str(\"The partial query to autocomplete.\"),\n language: ostr(\"Suggestion language (ISO 639-1, default 'en').\"),\n region: ostr(\"Region code (ISO 3166-1 alpha-2, default 'US').\"),\n }),\n (i) => client.youtube.suggestions(i)\n ),\n tool(\n \"YOUTUBE_VIDEO\",\n \"Scavio YouTube Video\",\n \"Fetch full metadata for a YouTube video by id or watch URL. Costs 1 credit.\",\n z.object({ video_id: str(\"YouTube video id or a full watch URL.\") }),\n (i) => client.youtube.video(i)\n ),\n tool(\n \"YOUTUBE_COMMENTS\",\n \"Scavio YouTube Comments\",\n \"List top-level comments on a YouTube video. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.comments(i)\n ),\n tool(\n \"YOUTUBE_COMMENT_REPLIES\",\n \"Scavio YouTube Comment Replies\",\n \"List replies to a YouTube comment using its reply cursor. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n reply_cursor: str(\"Reply cursor from a parent comment's 'reply_cursor' field.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.commentReplies(i)\n ),\n tool(\n \"YOUTUBE_TRANSCRIPT\",\n \"Scavio YouTube Transcript\",\n \"Fetch the transcript or timed captions for a YouTube video. Costs 8 credits.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n language: ostr(\"Caption language code (default 'en').\"),\n format: ostr(\"'text' for a plain transcript or 'srt' for timed subtitles (default 'text').\"),\n }),\n (i) => client.youtube.transcript(i as SdkOpts<typeof client.youtube.transcript>)\n ),\n tool(\n \"YOUTUBE_RELATED\",\n \"Scavio YouTube Related\",\n \"List videos related to a YouTube video. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.related(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_SEARCH\",\n \"Scavio YouTube Channel Search\",\n \"Search YouTube channels by keyword. Costs 1 credit.\",\n z.object({\n query: str(\"The channel search query.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelSearch(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL\",\n \"Scavio YouTube Channel\",\n \"Fetch YouTube channel details by id, @handle, or URL. Costs 1 credit.\",\n z.object({ channel_id: str(\"YouTube channel id, @handle, or channel URL.\") }),\n (i) => client.youtube.channel(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_VIDEOS\",\n \"Scavio YouTube Channel Videos\",\n \"List videos uploaded by a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelVideos(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_SHORTS\",\n \"Scavio YouTube Channel Shorts\",\n \"List Shorts posted by a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelShorts(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_COMMUNITY\",\n \"Scavio YouTube Channel Community\",\n \"List community posts from a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelCommunity(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_RESOLVE\",\n \"Scavio YouTube Channel Resolve\",\n \"Resolve a YouTube @handle or channel URL to a channel id. Costs 1 credit.\",\n z.object({ channel: str(\"A channel @handle or channel URL to resolve to a channel id.\") }),\n (i) => client.youtube.channelResolve(i)\n ),\n tool(\n \"YOUTUBE_STREAMS\",\n \"Scavio YouTube Streams\",\n \"Fetch playable or downloadable stream formats for a YouTube video. Costs 3 credits.\",\n z.object({ video_id: str(\"YouTube video id or a full watch URL.\") }),\n (i) => client.youtube.streams(i)\n )\n );\n }\n\n // /reddit/search takes ONLY query + cursor. `type` and `sort` were never real:\n // the API strips unknown fields, so they filtered nothing while making the agent\n // believe the result set was narrowed. Removed rather than kept as no-ops.\n // Sort defaults differ per endpoint (TOP for comments, HOT for a subreddit feed,\n // NEW for a user feed) and values are UPPERCASE; only the subreddit feed accepts\n // RISING. All twelve endpoints cost 1 credit.\n if (all || enableReddit) {\n tools.push(\n tool(\n \"REDDIT_SEARCH\",\n \"Scavio Reddit Search\",\n \"Search Reddit posts. Returns data.results with next_cursor and has_more; page with cursor. Results cannot be filtered or sorted. Costs 1 credit.\",\n z.object({\n query: str(\"The Reddit search query.\"),\n cursor: ostr(\"Pagination cursor: pass 'next_cursor' from a prior response.\"),\n }),\n (i) => client.reddit.search(i as SdkOpts<typeof client.reddit.search>)\n ),\n tool(\n \"REDDIT_SEARCH_SUGGESTIONS\",\n \"Scavio Reddit Search Suggestions\",\n \"Get Reddit search autocomplete suggestions for a query. Returns data.suggestions (plain strings) and total_count. Costs 1 credit.\",\n z.object({ query: str(\"The partial or full query to expand.\") }),\n (i) => client.reddit.searchSuggestions(i)\n ),\n tool(\n \"REDDIT_POST\",\n \"Scavio Reddit Post\",\n \"Fetch one Reddit post by URL or post id. Returns a FLAT post object under data (post_id, title, text, url, subreddit, author, score, upvote_ratio, num_comments, created_at, is_nsfw, is_video, thumbnail, media); comments are NOT included - call REDDIT_POST_COMMENTS for those. Costs 1 credit.\",\n z.object({\n url: ostr(\"Full URL of the Reddit post. Provide this or post_id.\"),\n post_id: ostr(\"Post fullname (t3_...) or bare id. Provide this or url.\"),\n }),\n (i) => client.reddit.post(i)\n ),\n tool(\n \"REDDIT_POST_COMMENTS\",\n \"Scavio Reddit Post Comments\",\n \"List top-level comments on a Reddit post. Returns data.comments with next_cursor and has_more; each comment carries a reply_cursor for REDDIT_COMMENT_REPLIES. Costs 1 credit.\",\n z.object({\n post_id: str(\"Post fullname (t3_...), bare id, or post URL.\"),\n sort: ostr(\"Comment sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to TOP.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.postComments(i as SdkOpts<typeof client.reddit.postComments>)\n ),\n tool(\n \"REDDIT_COMMENT_REPLIES\",\n \"Scavio Reddit Comment Replies\",\n \"List replies to one Reddit comment. cursor is REQUIRED here and must be a comment's 'reply_cursor' from REDDIT_POST_COMMENTS, not a 'next_cursor'. Costs 1 credit.\",\n z.object({\n post_id: str(\"Post fullname (t3_...) the comment belongs to.\"),\n cursor: str(\"A comment's 'reply_cursor' from REDDIT_POST_COMMENTS. Required.\"),\n sort: ostr(\"Comment sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to TOP.\"),\n }),\n (i) => client.reddit.commentReplies(i as SdkOpts<typeof client.reddit.commentReplies>)\n ),\n tool(\n \"REDDIT_SUBREDDIT\",\n \"Scavio Reddit Subreddit\",\n \"Fetch a subreddit's profile: title, description, subscribers, active_count, type, icon, banner and created_at. Costs 1 credit.\",\n z.object({ subreddit: str(\"Subreddit name without the r/ prefix, e.g. 'AskReddit'.\") }),\n (i) => client.reddit.subreddit(i)\n ),\n tool(\n \"REDDIT_SUBREDDIT_POSTS\",\n \"Scavio Reddit Subreddit Posts\",\n \"List posts in a subreddit feed. Returns data.posts with next_cursor and has_more. This feed shape has no text and no thumbnail - use REDDIT_POST for a post's body. Costs 1 credit.\",\n z.object({\n subreddit: str(\"Subreddit name without the r/ prefix.\"),\n sort: ostr(\"Feed sort order (UPPERCASE): 'BEST', 'HOT', 'NEW', 'TOP', 'CONTROVERSIAL', or 'RISING'. Defaults to HOT. This is the only endpoint accepting RISING.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.subredditPosts(i as SdkOpts<typeof client.reddit.subredditPosts>)\n ),\n tool(\n \"REDDIT_USER\",\n \"Scavio Reddit User\",\n \"Fetch a redditor's profile: karma split, account_type, avatar, description, verification flags and created_at. Costs 1 credit.\",\n z.object({ username: str(\"Redditor username without the u/ prefix, e.g. 'spez'.\") }),\n (i) => client.reddit.user(i)\n ),\n tool(\n \"REDDIT_USER_POSTS\",\n \"Scavio Reddit User Posts\",\n \"List posts submitted by a redditor. Returns data.posts with next_cursor and has_more. Costs 1 credit.\",\n z.object({\n username: str(\"Redditor username without the u/ prefix.\"),\n sort: ostr(\"Sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to NEW.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.userPosts(i as SdkOpts<typeof client.reddit.userPosts>)\n ),\n tool(\n \"REDDIT_USER_COMMENTS\",\n \"Scavio Reddit User Comments\",\n \"List comments written by a redditor. Returns data.comments with next_cursor and has_more; each item nests the post it belongs to. Costs 1 credit.\",\n z.object({\n username: str(\"Redditor username without the u/ prefix.\"),\n sort: ostr(\"Sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to NEW.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.userComments(i as SdkOpts<typeof client.reddit.userComments>)\n ),\n tool(\n \"REDDIT_POPULAR\",\n \"Scavio Reddit Popular\",\n \"List the site-wide r/popular feed. Returns data.posts with next_cursor and has_more. Costs 1 credit.\",\n z.object({ cursor: ostr(\"Pagination cursor from a prior response. Omit for page 1.\") }),\n (i) => client.reddit.popular(i)\n ),\n tool(\n \"REDDIT_TRENDING\",\n \"Scavio Reddit Trending\",\n \"List Reddit's currently trending searches. Returns data.trending (query plus raw_query) and total_count. Takes no parameters. Costs 1 credit.\",\n z.object({}),\n () => client.reddit.trending()\n )\n );\n }\n\n if (all || enableTiktok) {\n tools.push(\n tool(\n \"TIKTOK_PROFILE\",\n \"Scavio TikTok Profile\",\n \"Fetch a TikTok user profile by username or secUid. Costs 1 credit.\",\n z.object({\n username: ostr(\"TikTok username (without @). Provide this or sec_user_id.\"),\n sec_user_id: ostr(\"TikTok secUid. Provide this or username.\"),\n }),\n (i) => client.tiktok.profile(i)\n ),\n tool(\n \"TIKTOK_USER_POSTS\",\n \"Scavio TikTok User Posts\",\n \"List a TikTok user's posts by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of posts to return.\"),\n sort_type: ostr(\"Sort order for posts.\"),\n }),\n (i) => client.tiktok.userPosts(i as SdkOpts<typeof client.tiktok.userPosts>)\n ),\n tool(\n \"TIKTOK_VIDEO\",\n \"Scavio TikTok Video\",\n \"Fetch a TikTok video by id. Costs 1 credit.\",\n z.object({ video_id: str(\"TikTok video id.\") }),\n (i) => client.tiktok.video(i)\n ),\n tool(\n \"TIKTOK_VIDEO_COMMENTS\",\n \"Scavio TikTok Video Comments\",\n \"List comments on a TikTok video. Costs 1 credit.\",\n z.object({\n video_id: str(\"TikTok video id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of comments to return.\"),\n }),\n (i) => client.tiktok.videoComments(i)\n ),\n tool(\n \"TIKTOK_COMMENT_REPLIES\",\n \"Scavio TikTok Comment Replies\",\n \"List replies to a TikTok video comment. Costs 1 credit.\",\n z.object({\n video_id: str(\"TikTok video id.\"),\n comment_id: str(\"Parent comment id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of replies to return.\"),\n }),\n (i) => client.tiktok.commentReplies(i)\n ),\n tool(\n \"TIKTOK_SEARCH_VIDEOS\",\n \"Scavio TikTok Search Videos\",\n \"Search TikTok videos by keyword. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of videos to return.\"),\n sort_type: ostr(\"Sort order for results.\"),\n publish_time: ostr(\"Publish-time filter.\"),\n }),\n (i) => client.tiktok.searchVideos(i as SdkOpts<typeof client.tiktok.searchVideos>)\n ),\n tool(\n \"TIKTOK_SEARCH_USERS\",\n \"Scavio TikTok Search Users\",\n \"Search TikTok users by keyword. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of users to return.\"),\n }),\n (i) => client.tiktok.searchUsers(i)\n ),\n tool(\n \"TIKTOK_HASHTAG\",\n \"Scavio TikTok Hashtag\",\n \"Fetch a TikTok hashtag by name or id. Costs 1 credit.\",\n z.object({\n hashtag_name: ostr(\"Hashtag name (without #). Provide this or hashtag_id.\"),\n hashtag_id: ostr(\"Hashtag id. Provide this or hashtag_name.\"),\n }),\n (i) => client.tiktok.hashtag(i)\n ),\n tool(\n \"TIKTOK_HASHTAG_VIDEOS\",\n \"Scavio TikTok Hashtag Videos\",\n \"List videos for a TikTok hashtag by id. Costs 1 credit.\",\n z.object({\n hashtag_id: str(\"Hashtag id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of videos to return.\"),\n }),\n (i) => client.tiktok.hashtagVideos(i)\n ),\n tool(\n \"TIKTOK_USER_FOLLOWERS\",\n \"Scavio TikTok User Followers\",\n \"List a TikTok user's followers by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n count: onum(\"Number of followers to return.\"),\n page_token: ostr(\"Pagination token.\"),\n min_time: onum(\"Minimum timestamp filter.\"),\n }),\n (i) => client.tiktok.userFollowers(i)\n ),\n tool(\n \"TIKTOK_USER_FOLLOWINGS\",\n \"Scavio TikTok User Followings\",\n \"List the accounts a TikTok user follows, by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n count: onum(\"Number of followings to return.\"),\n page_token: ostr(\"Pagination token.\"),\n min_time: onum(\"Minimum timestamp filter.\"),\n }),\n (i) => client.tiktok.userFollowings(i)\n )\n );\n }\n\n // TikTok Shop: 8 endpoints, 1 credit each. Two different region enums on\n // purpose - the listing endpoints serve US and GB only, everything else serves\n // the full eight, and /tiktok-shop/search takes no region at all (US catalog).\n // Cursors are opaque blobs from a prior next_cursor; a foreign cursor 400s.\n if (all || enableTiktokShop) {\n tools.push(\n tool(\n \"TIKTOK_SHOP_SEARCH\",\n \"Scavio TikTok Shop Search\",\n \"Search TikTok Shop products by keyword (US catalog only), up to 30 per page with exact prices, ratings and shop details. One of the three endpoints that return exact prices. Paginate with next_cursor and dedupe by product_id across pages. Costs 1 credit.\",\n z.object({\n search: str(\"Search query (1-200 characters). The keyword field is named 'search', not 'query'.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.tiktokShop.search(i)\n ),\n tool(\n \"TIKTOK_SHOP_SEARCH_SUGGESTIONS\",\n \"Scavio TikTok Shop Search Suggestions\",\n \"Expand a partial TikTok Shop query into keyword suggestions across 8 marketplace regions. Suggestions are not guaranteed prefix matches: a misspelling returns typo corrections, and results can include brand and shop names. Costs 1 credit.\",\n z.object({\n search: str(\"Partial query to expand (1-100 characters). The field is 'search', not 'query'.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.searchSuggestions(i as SdkOpts<typeof client.tiktokShop.searchSuggestions>)\n ),\n tool(\n \"TIKTOK_SHOP_PRODUCT\",\n \"Scavio TikTok Shop Product\",\n \"Full TikTok Shop product detail: description, images, variants with stock, shipping, shop profile, category path and top reviews. Two limits: it does NOT return a price (upstream masks it - get prices from TIKTOK_SHOP_SEARCH, TIKTOK_SHOP_SHOP_PRODUCTS or TIKTOK_SHOP_CATEGORY_PRODUCTS), and it resolves only about 44% of the product ids returned by search, so a 404 is a normal outcome to skip rather than retry. Costs 1 credit.\",\n z.object({\n product_id: str(\"TikTok Shop product id (6-25 digits).\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.product(i as SdkOpts<typeof client.tiktokShop.product>)\n ),\n tool(\n \"TIKTOK_SHOP_PRODUCT_REVIEWS\",\n \"Scavio TikTok Shop Product Reviews\",\n \"Paginated TikTok Shop product reviews with text, images, star histogram and verified-purchase flags, up to 200 per call. total_reviews drifts between calls and must NOT be used to compute a page count - page with has_more instead. Often works for ids TIKTOK_SHOP_PRODUCT cannot resolve. Costs 1 credit.\",\n z.object({\n product_id: str(\"TikTok Shop product id (6-25 digits).\"),\n page: onum(\"1-based page number (1-500, default 1).\"),\n page_size: onum(\"Reviews per page (1-200, default 20).\"),\n sort: ostr(\"'relevant' (default) is text-complete and image-heavy; 'recent' is fresher but far more text-sparse.\"),\n rating: onum(\"Only reviews with this star rating (1-5).\"),\n has_media: obool(\"Only reviews with a photo or video. Shares one upstream slot with verified_only, and wins when both are set.\"),\n verified_only: obool(\"Only verified purchases. Ignored when has_media is also set.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.productReviews(i as SdkOpts<typeof client.tiktokShop.productReviews>)\n ),\n tool(\n \"TIKTOK_SHOP_CATEGORIES\",\n \"Scavio TikTok Shop Categories\",\n \"The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two levels deep. Category ids are identical in every region and names are always English. Takes no parameters. Costs 1 credit.\",\n z.object({}),\n () => client.tiktokShop.categories()\n ),\n tool(\n \"TIKTOK_SHOP_CATEGORY_PRODUCTS\",\n \"Scavio TikTok Shop Category Products\",\n \"Products listed under a category id from TIKTOK_SHOP_CATEGORIES, with exact prices. Level 1 or 2 ids both work. Page size is inconsistent upstream (15 to 20), so always paginate with next_cursor; when has_more turns false after a few pages that is the end of a shallow listing, not an error. Costs 1 credit.\",\n z.object({\n category_id: str(\"Category id from TIKTOK_SHOP_CATEGORIES; level 1 or 2 both work.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n region: ostr(\"Marketplace region, 'US' (default) or 'GB' only - not the 8-region list.\"),\n }),\n (i) => client.tiktokShop.categoryProducts(i as SdkOpts<typeof client.tiktokShop.categoryProducts>)\n ),\n tool(\n \"TIKTOK_SHOP_SHOP_PRODUCTS\",\n \"Scavio TikTok Shop Shop Products\",\n \"A shop's TikTok Shop catalog, 30 per page, with exact prices. Shop follower count, location and shop-level rating are not available here - call TIKTOK_SHOP_PRODUCT for the full shop profile. Costs 1 credit.\",\n z.object({\n shop_id: str(\"TikTok Shop seller id (also called seller_id elsewhere on TikTok).\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.shopProducts(i as SdkOpts<typeof client.tiktokShop.shopProducts>)\n ),\n tool(\n \"TIKTOK_SHOP_RESOLVE\",\n \"Scavio TikTok Shop Resolve\",\n \"Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready for the other TikTok Shop tools. Accepts shop.tiktok.com product and store pages, tiktok.com/view links, affiliate share links, and vt.tiktok.com short links. Costs 1 credit.\",\n z.object({ url: str(\"A TikTok Shop product or store URL, affiliate share link, or vt.tiktok.com short link.\") }),\n (i) => client.tiktokShop.resolve(i)\n )\n );\n }\n\n if (all || enableInstagram) {\n tools.push(\n tool(\n \"INSTAGRAM_PROFILE\",\n \"Scavio Instagram Profile\",\n \"Fetch an Instagram profile by username or user id. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n }),\n (i) => client.instagram.profile(i)\n ),\n tool(\n \"INSTAGRAM_USER_POSTS\",\n \"Scavio Instagram User Posts\",\n \"List an Instagram user's posts. Costs 2 credits, the cheapest Instagram endpoint.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of posts to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userPosts(i)\n ),\n tool(\n \"INSTAGRAM_USER_REELS\",\n \"Scavio Instagram User Reels\",\n \"List an Instagram user's reels. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of reels to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userReels(i)\n ),\n tool(\n \"INSTAGRAM_USER_TAGGED\",\n \"Scavio Instagram User Tagged\",\n \"List posts an Instagram user is tagged in. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of tagged posts to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userTagged(i)\n ),\n tool(\n \"INSTAGRAM_USER_STORIES\",\n \"Scavio Instagram User Stories\",\n \"Fetch an Instagram user's current stories. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n }),\n (i) => client.instagram.userStories(i)\n ),\n tool(\n \"INSTAGRAM_POST\",\n \"Scavio Instagram Post\",\n \"Fetch an Instagram post by URL, media id, or shortcode. Costs 8 credits.\",\n z.object({\n url: ostr(\"Post URL. Provide one of url, media_id, or shortcode.\"),\n media_id: ostr(\"Post media id. Provide one of url, media_id, or shortcode.\"),\n shortcode: ostr(\"Post shortcode. Provide one of url, media_id, or shortcode.\"),\n }),\n (i) => client.instagram.post(i)\n ),\n tool(\n \"INSTAGRAM_POST_COMMENTS\",\n \"Scavio Instagram Post Comments\",\n \"List comments on an Instagram post by shortcode or URL. Costs 10 credits.\",\n z.object({\n shortcode: ostr(\"Post shortcode. Provide this or url.\"),\n url: ostr(\"Post URL. Provide this or shortcode.\"),\n cursor: ostr(\"Pagination cursor.\"),\n sort_order: ostr(\"Comment sort order.\"),\n }),\n (i) => client.instagram.postComments(i as SdkOpts<typeof client.instagram.postComments>)\n ),\n tool(\n \"INSTAGRAM_COMMENT_REPLIES\",\n \"Scavio Instagram Comment Replies\",\n \"List replies to an Instagram post comment. Costs 8 credits.\",\n z.object({\n media_id: str(\"Post media id.\"),\n comment_id: str(\"Parent comment id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.commentReplies(i)\n ),\n tool(\n \"INSTAGRAM_SEARCH_USERS\",\n \"Scavio Instagram Search Users\",\n \"Search Instagram users by keyword. Costs 10 credits.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.searchUsers(i)\n ),\n tool(\n \"INSTAGRAM_SEARCH_HASHTAGS\",\n \"Scavio Instagram Search Hashtags\",\n \"Search Instagram hashtags by keyword. Costs 10 credits.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.searchHashtags(i)\n ),\n tool(\n \"INSTAGRAM_USER_FOLLOWERS\",\n \"Scavio Instagram User Followers\",\n \"List an Instagram user's followers. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of followers to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userFollowers(i)\n ),\n tool(\n \"INSTAGRAM_USER_FOLLOWINGS\",\n \"Scavio Instagram User Followings\",\n \"List the accounts an Instagram user follows. Costs 10 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of followings to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userFollowings(i)\n )\n );\n }\n\n // X (Twitter): 11 endpoints, 1 credit each. The keyword field on search is\n // `search`, not `query`. search_type values are Capitalized while the comment\n // `rank` values are lowercase - that asymmetry is upstream's, not a typo.\n if (all || enableX) {\n tools.push(\n tool(\n \"X_SEARCH\",\n \"Scavio X Search\",\n \"Search X (Twitter) posts. Returns data.timeline with next_cursor, prev_cursor and has_more. Costs 1 credit.\",\n z.object({\n search: str(\"Search query (1-500 characters). The field is 'search', not 'query'.\"),\n search_type: ostr(\"Result category (Capitalized): 'Top' (default), 'Latest', 'People', 'Photos', or 'Videos'.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.search(i as SdkOpts<typeof client.x.search>)\n ),\n tool(\n \"X_TWEET\",\n \"Scavio X Tweet\",\n \"Fetch one X post by id. Returns the tweet object plus reply_to, in_reply_to_screen_name, in_reply_to_status_id, in_reply_to_user_id and sensitive. Costs 1 credit.\",\n z.object({ tweet_id: str(\"Numeric post id as a string, e.g. '1808168603721650364'.\") }),\n (i) => client.x.tweet(i)\n ),\n tool(\n \"X_TWEET_COMMENTS\",\n \"Scavio X Tweet Comments\",\n \"List replies to an X post. Returns data.timeline with next_cursor, prev_cursor and has_more. rank switches the upstream feed: 'latest' is chronological, 'top' is ranked. Costs 1 credit.\",\n z.object({\n tweet_id: str(\"Numeric post id as a string.\"),\n rank: ostr(\"Reply ordering (lowercase): 'top' (default, ranked) or 'latest' (chronological).\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.tweetComments(i as SdkOpts<typeof client.x.tweetComments>)\n ),\n tool(\n \"X_TWEET_RETWEETERS\",\n \"Scavio X Tweet Retweeters\",\n \"List the accounts that reposted an X post. Returns data.retweeters with next_cursor and has_more. Costs 1 credit.\",\n z.object({\n tweet_id: str(\"Numeric post id as a string.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.tweetRetweeters(i)\n ),\n tool(\n \"X_USER\",\n \"Scavio X User\",\n \"Fetch an X profile by handle: followers_count, friends_count, statuses_count, media_count, blue_verified, location, website, avatar, header_image and pinned_tweet_ids. Costs 1 credit.\",\n z.object({ screen_name: str(\"An X handle WITHOUT the @, e.g. 'elonmusk'.\") }),\n (i) => client.x.user(i)\n ),\n tool(\n \"X_USER_TWEETS\",\n \"Scavio X User Tweets\",\n \"List an X user's posts. Returns data.timeline plus pinned and user; there is no has_more on this endpoint, so page on next_cursor. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userTweets(i)\n ),\n tool(\n \"X_USER_REPLIES\",\n \"Scavio X User Replies\",\n \"List an X user's replies. Returns data.timeline with next_cursor and prev_cursor; no has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userReplies(i)\n ),\n tool(\n \"X_USER_MEDIA\",\n \"Scavio X User Media\",\n \"List an X user's posts that carry photos or videos. Returns data.timeline with next_cursor and prev_cursor; no has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userMedia(i)\n ),\n tool(\n \"X_USER_FOLLOWERS\",\n \"Scavio X User Followers\",\n \"List an X user's followers. Returns data.followers with followers_count, next_cursor and has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userFollowers(i)\n ),\n tool(\n \"X_USER_FOLLOWINGS\",\n \"Scavio X User Followings\",\n \"List the accounts an X user follows. The response array is data.following (singular), not followings, and there is no following_count. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userFollowings(i)\n ),\n tool(\n \"X_TRENDING\",\n \"Scavio X Trending\",\n \"List what is trending on X for one country. Returns data.trends with no cursor and no has_more. Costs 1 credit.\",\n z.object({ country: ostr(\"Country NAME, not an ISO code, e.g. 'UnitedStates' (the default).\") }),\n (i) => client.x.trending(i)\n )\n );\n }\n\n // LinkedIn: 9 live endpoints on three credit tiers - 1 for person, person/about,\n // company and post; 10 for the feeds, job search and post comments; 30 for job,\n // the most expensive endpoint in the API. The five retired endpoints\n // (person/contact, company/people, company/jobs, search/people, search/posts)\n // return 410 unbilled and are deliberately NOT exposed: an agent-facing tool\n // that can only fail is worse than no tool.\n if (all || enableLinkedin) {\n tools.push(\n tool(\n \"LINKEDIN_PERSON\",\n \"Scavio LinkedIn Person\",\n \"Fetch a full LinkedIn profile: headline, about, location, follower and connection counts, current_company, experiences, educations, honors_and_awards, bio_links and similar profiles. Costs 1 credit.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle, e.g. 'williamhgates'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n }),\n (i) => client.linkedin.person(i)\n ),\n tool(\n \"LINKEDIN_PERSON_ABOUT\",\n \"Scavio LinkedIn Person About\",\n \"The about-only slice of a LinkedIn profile: about, headline, education_summary, experiences, educations, honors_and_awards and bio_links. Same upstream call as LINKEDIN_PERSON, shaped down. Costs 1 credit.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n }),\n (i) => client.linkedin.personAbout(i)\n ),\n tool(\n \"LINKEDIN_PERSON_POSTS\",\n \"Scavio LinkedIn Person Posts\",\n \"A member's LinkedIn feed - their own posts, or posts they commented on or reacted to via type. 50 per page; advance with next_cursor. Costs 10 credits.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n type: ostr(\"Which feed: 'posts' (default), 'comments' (posts they commented on), or 'reactions' (posts they reacted to).\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.personPosts(i as SdkOpts<typeof client.linkedin.personPosts>)\n ),\n tool(\n \"LINKEDIN_COMPANY\",\n \"Scavio LinkedIn Company\",\n \"Fetch a LinkedIn company profile: description, website, industries, specialties, employee and follower counts, headquarters, locations, similar and affiliated companies, and featured_employees (a 4-6 person sample, the documented substitute for the retired employee directory). Costs 1 credit.\",\n z.object({\n company: ostr(\"Company universal name / slug, e.g. 'microsoft'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn company URL. Provide this or company.\"),\n }),\n (i) => client.linkedin.company(i)\n ),\n tool(\n \"LINKEDIN_COMPANY_POSTS\",\n \"Scavio LinkedIn Company Posts\",\n \"Recent posts from a LinkedIn company page, 50 per page; advance with next_cursor. There is no type selector here - that is person-only. Costs 10 credits.\",\n z.object({\n company: ostr(\"Company universal name / slug. Provide this or url.\"),\n url: ostr(\"Full LinkedIn company URL. Provide this or company.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.companyPosts(i)\n ),\n tool(\n \"LINKEDIN_SEARCH_JOBS\",\n \"Scavio LinkedIn Search Jobs\",\n \"Search LinkedIn job listings, 25 per page; advance with next_cursor. Upstream rotates its result set so pages overlap - dedupe by job id. Costs 10 credits.\",\n z.object({\n search: str(\"Search keyword, e.g. 'software engineer'. The field is 'search', not 'query'.\"),\n location: ostr(\"Geographic filter; omit to search everywhere.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.searchJobs(i)\n ),\n tool(\n \"LINKEDIN_JOB\",\n \"Scavio LinkedIn Job\",\n \"Full detail for one LinkedIn job listing, including the hiring company. The most expensive endpoint in the API - about 1 in 5 ids from LINKEDIN_SEARCH_JOBS has no detail record upstream and answers 404 unbilled, so skip rather than retry. Costs 30 credits.\",\n z.object({\n job_id: ostr(\"Job listing id, e.g. '4415427228'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn job URL. Provide this or job_id.\"),\n }),\n (i) => client.linkedin.job(i)\n ),\n tool(\n \"LINKEDIN_POST\",\n \"Scavio LinkedIn Post\",\n \"Full detail for one LinkedIn post: text, media, hashtags, tagged companies and people, reaction and comment counts, author, and its top visible comments. Costs 1 credit.\",\n z.object({\n post_id: ostr(\"Post id or activity urn, e.g. '7488618410256523265'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn post URL. Provide this or post_id.\"),\n }),\n (i) => client.linkedin.post(i)\n ),\n tool(\n \"LINKEDIN_POST_COMMENTS\",\n \"Scavio LinkedIn Post Comments\",\n \"Comments on a LinkedIn post with their replies. This is the only LinkedIn endpoint paginated by a 1-based integer page rather than a cursor, and page size varies upstream - keep paging until a page comes back empty. Costs 10 credits.\",\n z.object({\n post_id: ostr(\"Post id or activity urn. Provide this or url.\"),\n url: ostr(\"Full LinkedIn post URL. Provide this or post_id.\"),\n page: onum(\"1-based page number (default 1). Page size varies, so page until empty.\"),\n }),\n (i) => client.linkedin.postComments(i)\n )\n );\n }\n\n // Threads is BODY-PRICED: 2 credits addressed by user_id, 4 by username,\n // because the handle has to be resolved through people search first.\n if (all || enableThreads) {\n tools.push(\n tool(\n \"THREADS_PROFILE\",\n \"Scavio Threads Profile\",\n \"Profile details for a Threads user. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total): the upstream handle lookup is down, so the handle is resolved through people search first. Pass user_id instead to avoid that.\"),\n }),\n (i) => client.threads.profile(i as SdkOpts<typeof client.threads.profile>)\n ),\n tool(\n \"THREADS_USER_POSTS\",\n \"Scavio Threads User Posts\",\n \"A user's Threads posts, cursor-paginated via next_cursor. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total) because the handle has to be resolved through people search first.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.userPosts(i as SdkOpts<typeof client.threads.userPosts>)\n ),\n tool(\n \"THREADS_USER_REPLIES\",\n \"Scavio Threads User Replies\",\n \"A user's Threads replies, cursor-paginated via next_cursor. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total) because the handle has to be resolved through people search first.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.userReplies(i as SdkOpts<typeof client.threads.userReplies>)\n ),\n tool(\n \"THREADS_POST\",\n \"Scavio Threads Post\",\n \"A single Threads post, addressed by post_id or by its threads.net URL. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n post_id: ostr(\"Threads post id, e.g. '3349029093483693129'.\"),\n url: ostr(\"Full threads.net post URL (e.g. 'https://www.threads.net/@natgeo/post/C8xY'), as an alternative to post_id.\"),\n }),\n (i) => client.threads.post(i as SdkOpts<typeof client.threads.post>)\n ),\n tool(\n \"THREADS_POST_COMMENTS\",\n \"Scavio Threads Post Comments\",\n \"Replies to a Threads post, cursor-paginated via next_cursor. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n post_id: str(\"Threads post id, e.g. '3349029093483693129'.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.postComments(i as SdkOpts<typeof client.threads.postComments>)\n ),\n tool(\n \"THREADS_SEARCH_USERS\",\n \"Scavio Threads Search Users\",\n \"Search Threads profiles by name or handle. This is the only search Threads exposes - there is no post or content search - and it returns a single unpaginated page. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n query: str(\"Name or handle to search for (1-200 characters).\"),\n }),\n (i) => client.threads.searchUsers(i as SdkOpts<typeof client.threads.searchUsers>)\n )\n );\n }\n\n // Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\n // Kwai international (kwai.com) is not served upstream; only kuaishou.com links\n // resolve. Upstream hides failures inside HTTP 200, so check the payload.\n if (all || enableKuaishou) {\n tools.push(\n tool(\n \"KUAISHOU_PROFILE\",\n \"Scavio Kuaishou Profile\",\n \"Profile details for a Kuaishou user. Costs 10 credits, the dearest single-object call on the platform: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n }),\n (i) => client.kuaishou.profile(i as SdkOpts<typeof client.kuaishou.profile>)\n ),\n tool(\n \"KUAISHOU_USER_POSTS\",\n \"Scavio Kuaishou User Posts\",\n \"A Kuaishou user's top posts, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.userPosts(i as SdkOpts<typeof client.kuaishou.userPosts>)\n ),\n tool(\n \"KUAISHOU_USER_LIVE\",\n \"Scavio Kuaishou User Live\",\n \"A Kuaishou user's current live-stream status. Not paginated. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n }),\n (i) => client.kuaishou.userLive(i as SdkOpts<typeof client.kuaishou.userLive>)\n ),\n tool(\n \"KUAISHOU_USER_RESOLVE\",\n \"Scavio Kuaishou User Resolve\",\n \"Turns a Kuaishou share link into a user id. Only kuaishou.com and v.kuaishou.com links are accepted; Kwai international (kwai.com) is not served upstream. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n share_link: str(\"A kuaishou.com or v.kuaishou.com URL; kwai.com links are rejected.\"),\n }),\n (i) => client.kuaishou.userResolve(i as SdkOpts<typeof client.kuaishou.userResolve>)\n ),\n tool(\n \"KUAISHOU_VIDEO\",\n \"Scavio Kuaishou Video\",\n \"A single Kuaishou video by photo id or URL. Provide photo_id or url. Costs 2 credits: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: ostr(\"Kuaishou photo (video) id, non-empty.\"),\n url: ostr(\"Full kuaishou.com video URL, as an alternative to photo_id.\"),\n }),\n (i) => client.kuaishou.video(i as SdkOpts<typeof client.kuaishou.video>)\n ),\n tool(\n \"KUAISHOU_VIDEO_COMMENTS\",\n \"Scavio Kuaishou Video Comments\",\n \"Comments on a Kuaishou video, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: str(\"Kuaishou photo (video) id, non-empty.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.videoComments(i as SdkOpts<typeof client.kuaishou.videoComments>)\n ),\n tool(\n \"KUAISHOU_COMMENT_REPLIES\",\n \"Scavio Kuaishou Comment Replies\",\n \"Replies under a root comment on a Kuaishou video, cursor-paginated via next_cursor; count sizes the page (1-50). Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: str(\"Kuaishou photo (video) id, non-empty.\"),\n root_comment_id: str(\"Id of the top-level comment whose replies you want, from video_comments.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n count: onum(\"Replies per page, 1-50. Omit to use the upstream default.\"),\n }),\n (i) => client.kuaishou.commentReplies(i as SdkOpts<typeof client.kuaishou.commentReplies>)\n ),\n tool(\n \"KUAISHOU_VIDEOS_BATCH\",\n \"Scavio Kuaishou Videos Batch\",\n \"Several Kuaishou videos in one call, hard-capped at 20 photo ids. Costs 40 credits, the dearest call on the platform: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_ids: arrstr(\"Kuaishou photo (video) ids, 1-20 per call; more than 20 is rejected.\"),\n }),\n (i) => client.kuaishou.videosBatch(i as SdkOpts<typeof client.kuaishou.videosBatch>)\n ),\n tool(\n \"KUAISHOU_SEARCH\",\n \"Scavio Kuaishou Search\",\n \"Mixed-result search across Kuaishou, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.search(i as SdkOpts<typeof client.kuaishou.search>)\n ),\n tool(\n \"KUAISHOU_SEARCH_VIDEOS\",\n \"Scavio Kuaishou Search Videos\",\n \"Kuaishou video search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchVideos(i as SdkOpts<typeof client.kuaishou.searchVideos>)\n ),\n tool(\n \"KUAISHOU_SEARCH_USERS\",\n \"Scavio Kuaishou Search Users\",\n \"Kuaishou user search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchUsers(i as SdkOpts<typeof client.kuaishou.searchUsers>)\n ),\n tool(\n \"KUAISHOU_SEARCH_LIVE\",\n \"Scavio Kuaishou Search Live\",\n \"Kuaishou live-stream search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchLive(i as SdkOpts<typeof client.kuaishou.searchLive>)\n ),\n tool(\n \"KUAISHOU_TAG_FEED\",\n \"Scavio Kuaishou Tag Feed\",\n \"Posts under a Kuaishou hashtag, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n tag: str(\"Hashtag text without the leading '#', 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.tagFeed(i as SdkOpts<typeof client.kuaishou.tagFeed>)\n ),\n tool(\n \"KUAISHOU_TRENDING\",\n \"Scavio Kuaishou Trending\",\n \"Kuaishou hot / live / shopping / brand / music leaderboards. One board per call, not paginated. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n board: ostr(\"Leaderboard to return; defaults to 'hot' when omitted. Accepted values: 'hot', 'live', 'shopping', 'brand', 'music'.\"),\n }),\n (i) => client.kuaishou.trending(i as SdkOpts<typeof client.kuaishou.trending>)\n )\n );\n }\n\n if (all || enableEbay) {\n tools.push(\n tool(\n \"EBAY_SEARCH\",\n \"Scavio eBay Search\",\n \"Search live or SOLD eBay listings: price, condition, bids, shipping, seller, feedback. Provide query or seller; per_page accepts only 60, 120 or 240. Costs 1 credit.\",\n z.object({\n query: ostr(\"Keyword to search (1-500 characters). Optional: a seller-only search pages that seller's whole catalogue.\"),\n seller: ostr(\"Restrict results to one seller's listings (1-64 characters), as in ebay.com/usr/<name>. Can be sent with no query.\"),\n page: onum(\"Results page, 1-based.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. eBay's 'Distance: nearest first' is deliberately unsupported (it ranks against our proxy exit, not the caller). Accepted values: 'best_match', 'ending_soonest', 'newly_listed', 'price_low', 'price_high'.\"),\n min_price: onum(\"Minimum price, inclusive. Must be 0 or greater.\"),\n max_price: onum(\"Maximum price, inclusive. Must be 0 or greater.\"),\n condition: ostr(\"Item condition filter. 'refurbished' is eBay's parent condition, not one of its three graded tiers. Accepted values: 'new', 'open_box', 'refurbished', 'used', 'for_parts'.\"),\n buying_format: ostr(\"Listing format: auction, fixed price (buy_it_now), or fixed price accepting offers (best_offer).\"),\n free_shipping: obool(\"Only listings with free shipping.\"),\n sold: obool(\"Search completed listings that actually SOLD, for price research. eBay publishes no headline count on this view, so total_results is null.\"),\n category_id: ostr(\"eBay category id; must be numeric (e.g. '112529'). An unrecognised id returns the UNFILTERED set under a 200.\"),\n per_page: onum(\"Listings per page: 60, 120 or 240 only. Defaults to 60; eBay silently falls back to 60 for anything else.\"),\n }),\n (i) => client.ebay.search(i as SdkOpts<typeof client.ebay.search>)\n ),\n tool(\n \"EBAY_PRODUCT\",\n \"Scavio eBay Product\",\n \"One eBay listing in full: price, condition, images, item specifics, shipping, returns, auction state, seller. Costs 1 credit.\",\n z.object({\n item_id: str(\"eBay item number (e.g. '168591664725'), or a full ebay.com/itm/... listing URL; tracking parameters on a pasted URL are discarded.\"),\n }),\n (i) => client.ebay.product(i as SdkOpts<typeof client.ebay.product>)\n ),\n tool(\n \"EBAY_SELLER\",\n \"Scavio eBay Seller\",\n \"eBay seller profile card: store name, feedback score and %, items sold, followers, location, categories. Profile only: page a catalogue with search(seller=...). Costs 1 credit.\",\n z.object({\n seller: str(\"eBay username as it appears in ebay.com/usr/<name> (1-64 characters), which is what seller_name on a search or product result returns.\"),\n }),\n (i) => client.ebay.seller(i as SdkOpts<typeof client.ebay.seller>)\n )\n );\n }\n\n if (all || enableTarget) {\n tools.push(\n tool(\n \"TARGET_SEARCH\",\n \"Scavio Target Search\",\n \"Search Target.com, the US retailer: prices, ratings, badges and promotions. Up to 28 results per page; rendered upstream, so expect around 9 seconds. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword (1-500 characters).\"),\n page: onum(\"Results page, 1-based.\"),\n count: onum(\"Results per page, 1-28. Defaults to 24; Target rejects anything above 28 outright.\"),\n sort: ostr(\"Result sort order. Defaults to 'relevance'. Accepted values: 'relevance', 'featured', 'price_low', 'price_high', 'rating_high', 'best_seller', 'newest'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991', the store target.com uses with no store context.\"),\n }),\n (i) => client.target.search(i as SdkOpts<typeof client.target.search>)\n ),\n tool(\n \"TARGET_CATEGORY\",\n \"Scavio Target Category\",\n \"Products in a Target category, same shape as search plus the category breadcrumb. Up to 28 per page; the slowest Target endpoint at around 37 seconds. Costs 1 credit.\",\n z.object({\n category_id: str(\"Target category id: the segment after 'N-' in a target.com /c/ URL (target.com/c/apple/-/N-5xtg6 -> '5xtg6').\"),\n page: onum(\"Results page, 1-based.\"),\n count: onum(\"Results per page, 1-28. Defaults to 24; Target rejects anything above 28 outright.\"),\n sort: ostr(\"Result sort order. Defaults to 'relevance'. Accepted values: 'relevance', 'featured', 'price_low', 'price_high', 'rating_high', 'best_seller', 'newest'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.category(i as SdkOpts<typeof client.target.category>)\n ),\n tool(\n \"TARGET_PRODUCT\",\n \"Scavio Target Product\",\n \"Target product details by TCIN: price, rating, images, specifications, variants, return policy, fulfillment. seller_id/seller_name are null for stock sold by Target. Costs 1 credit.\",\n z.object({\n tcin: str(\"Target catalog id (tcin, e.g. '1010453160'). A colour/size child tcin is answered by its variation parent, with the child present in 'variants'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.product(i as SdkOpts<typeof client.target.product>)\n ),\n tool(\n \"TARGET_REVIEWS\",\n \"Scavio Target Reviews\",\n \"Target reviews with the rating breakdown, per-attribute averages and guest photos. 8 review bodies maximum and no paging; expect around 40 seconds. Costs 1 credit.\",\n z.object({\n tcin: str(\"Target catalog id (tcin, e.g. '1010453160').\"),\n limit: onum(\"Trim the returned reviews to at most this many (1 or greater). Target publishes 8 anonymously and offers no paging, so this only trims.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.reviews(i as SdkOpts<typeof client.target.reviews>)\n )\n );\n }\n\n if (all || enableHomeDepot) {\n tools.push(\n tool(\n \"HOME_DEPOT_SEARCH\",\n \"Scavio Home Depot Search\",\n \"Search Home Depot: price and promotions, brand and model, ratings, badges, per-store pickup/delivery. Page size is fixed at 12 and cannot be changed. Costs 2 credits.\",\n z.object({\n query: str(\"Search keyword (1-500 characters).\"),\n page: onum(\"Results page, 1-based. Home Depot serves 12 products per page and offers no way to change that, so paging is the only way to read further.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Closed enum: Home Depot answers an unknown sort with an empty page that is still billed. 'Newest' is absent - it is rejected on keyword search. Accepted values: 'best_match', 'top_sellers', 'top_rated', 'price_low', 'price_high'.\"),\n min_price: onum(\"Minimum price, inclusive. Must be 0 or greater.\"),\n max_price: onum(\"Maximum price, inclusive. Must be 0 or greater.\"),\n }),\n (i) => client.homeDepot.search(i as SdkOpts<typeof client.homeDepot.search>)\n ),\n tool(\n \"HOME_DEPOT_PRODUCT\",\n \"Scavio Home Depot Product\",\n \"Full Home Depot item detail: pricing, images and videos, spec table, dimensions, bullets, documents, return policy. Carries a 10-review preview only. Costs 2 credits.\",\n z.object({\n item_id: str(\"Home Depot item id (e.g. '325479354'), or a full homedepot.com/p/... product URL; tracking parameters on a pasted URL are discarded.\"),\n }),\n (i) => client.homeDepot.product(i as SdkOpts<typeof client.homeDepot.product>)\n ),\n tool(\n \"HOME_DEPOT_REVIEWS\",\n \"Scavio Home Depot Reviews\",\n \"One page of full Home Depot review bodies, the rating distribution, per-attribute ratings, photos and seller responses. 30 reviews per page. Costs 2 credits.\",\n z.object({\n item_id: str(\"Home Depot item id (e.g. '325479354'), or a full homedepot.com/p/... product URL; tracking parameters on a pasted URL are discarded.\"),\n page: onum(\"Reviews page, 1-based. 30 reviews per page; 'total_pages' in the response is the last one that exists, and asking past it is a 404.\"),\n }),\n (i) => client.homeDepot.reviews(i as SdkOpts<typeof client.homeDepot.reviews>)\n )\n );\n }\n\n if (all || enableZillow) {\n tools.push(\n tool(\n \"ZILLOW_SEARCH\",\n \"Scavio Zillow Search\",\n \"Zillow listings in a region: price, beds, baths, living area, Zestimate, coordinates, images, days on market. A bare ZIP works alone but cannot be combined with a filter or a sort. Costs 1 credit.\",\n z.object({\n location: str(\"Region to search (1-200 characters): a Zillow slug ('austin-tx'), a human form ('Austin, TX'), a ZIP, or a pasted zillow.com search URL. A ZIP works alone but cannot be combined with a filter or sort; an unresolvable region is a 404.\"),\n listing_status: ostr(\"Which listings to return. Defaults to 'for_sale'. Accepted values: 'for_sale', 'for_rent', 'sold'.\"),\n page: onum(\"Results page, 1-based.\"),\n sort: ostr(\"Result sort order. Sorts that rank against a signed-in profile (saved/featured/personalised) are unsupported - we are never signed in. Accepted values: 'relevance', 'recommended', 'newest', 'price_low', 'price_high', 'payment_low', 'payment_high', 'beds', 'baths', 'sqft', 'lot_size', 'zestimate_low', 'zestimate_high', 'recent_change'.\"),\n min_price: onum(\"Minimum price, inclusive (0 or greater). On listing_status='for_rent' this is MONTHLY RENT - Zillow files rent under its payment filter.\"),\n max_price: onum(\"Maximum price, inclusive (0 or greater). On listing_status='for_rent' this is MONTHLY RENT.\"),\n beds_min: onum(\"Minimum bedrooms; whole number, 0 or greater.\"),\n beds_max: onum(\"Maximum bedrooms; whole number, 0 or greater.\"),\n baths_min: onum(\"Minimum bathrooms, 0 or greater. Half-baths are allowed (1.5).\"),\n baths_max: onum(\"Maximum bathrooms, 0 or greater. Half-baths are allowed (1.5).\"),\n sqft_min: onum(\"Minimum living area in square feet; whole number, 0 or greater.\"),\n sqft_max: onum(\"Maximum living area in square feet; whole number, 0 or greater.\"),\n lot_size_min: onum(\"Minimum lot size in square feet; whole number, 0 or greater.\"),\n lot_size_max: onum(\"Maximum lot size in square feet; whole number, 0 or greater.\"),\n year_built_min: onum(\"Earliest year built; whole number, 0 or greater.\"),\n year_built_max: onum(\"Latest year built; whole number, 0 or greater.\"),\n max_hoa: onum(\"Maximum monthly HOA fee in dollars, 0 or greater.\"),\n home_type: ostr(\"Property type filter. Accepted values: 'houses', 'townhomes', 'multi_family', 'condos', 'apartments', 'manufactured', 'lots_land'.\"),\n days_on_zillow: ostr(\"Listed - or, with listing_status='sold', sold - within the last N days. Closed enum: an unrecognised value returns the UNFILTERED set under a 200. Accepted values: '1', '7', '14', '30', '90', '6m', '12m', '24m', '36m'.\"),\n keywords: ostr(\"Free-text match against the listing description (1-200 characters).\"),\n has_pool: obool(\"Only listings with a pool.\"),\n has_garage: obool(\"Only listings with a garage.\"),\n has_air_conditioning: obool(\"Only listings with air conditioning.\"),\n is_waterfront: obool(\"Only waterfront listings.\"),\n has_basement: obool(\"Only listings with a basement.\"),\n is_new_construction: obool(\"Only new-construction listings.\"),\n has_open_house: obool(\"Only listings with an upcoming open house.\"),\n price_reduced: obool(\"Only listings whose price was reduced.\"),\n is_3d_tour: obool(\"Only listings with a 3D tour.\"),\n }),\n (i) => client.zillow.search(i as SdkOpts<typeof client.zillow.search>)\n ),\n tool(\n \"ZILLOW_PROPERTY\",\n \"Scavio Zillow Property\",\n \"Full Zillow listing: price and price history, Zestimate, tax history, RESO facts, rooms, schools, open houses, photos. Rental buildings return floor plans instead. Costs 1 credit.\",\n z.object({\n zpid: str(\"Zillow property id (e.g. '29414894'), a full /homedetails/ URL, or a rental building URL (zillow.com/apartments/...). The building form is required for buildings: they have no zpid a caller can see.\"),\n }),\n (i) => client.zillow.property(i as SdkOpts<typeof client.zillow.property>)\n ),\n tool(\n \"ZILLOW_AGENT_REVIEWS\",\n \"Scavio Zillow Agent Reviews\",\n \"A Zillow AGENT's profile and reviews: rating, bodies with sub-ratings, specialties, licenses, service areas, sales counts. Zillow server-renders the first five. Costs 1 credit.\",\n z.object({\n screen_name: str(\"Zillow agent profile screen name as it appears in zillow.com/profile/<name>/ (1-200 characters, may contain spaces), or a full profile URL.\"),\n }),\n (i) => client.zillow.agentReviews(i as SdkOpts<typeof client.zillow.agentReviews>)\n )\n );\n }\n\n if (all || enableBooking) {\n tools.push(\n tool(\n \"BOOKING_SEARCH\",\n \"Scavio Booking.com Search\",\n \"Booking.com properties for a destination and stay: live nightly price, review score, star rating, location, room type, deal badges. 25 properties per page. Provide destination or dest_id. Costs 1 credit.\",\n z.object({\n destination: ostr(\"Destination to search, e.g. 'Paris' (1-200 characters). Required unless dest_id is given.\"),\n dest_id: ostr(\"Numeric Booking.com destination id, as an alternative to destination.\"),\n dest_type: ostr(\"What dest_id refers to. Requires dest_id and is rejected without it, because Booking silently ignores a lone dest_type. Accepted values: 'city', 'region', 'country', 'district', 'landmark', 'airport', 'hotel'.\"),\n page: onum(\"Results page, 1-based. 25 properties per page, 1 credit each.\"),\n sort_by: ostr(\"Result sort order (default 'popularity'). Accepted values: 'popularity', 'price_low', 'price_high', 'stars_high', 'stars_low', 'stars_and_price', 'distance', 'review_score'.\"),\n min_price: onum(\"Minimum price PER NIGHT in `currency`, >= 0. Must not exceed max_price.\"),\n max_price: onum(\"Maximum price PER NIGHT in `currency`, >= 0.\"),\n stars: oarrnum(\"Star ratings to include, each 1-5, 1-5 values, OR'd together (e.g. [4, 5]).\"),\n min_review_score: ostr(\"Minimum guest review score. Only '6', '7', '8' and '9' exist upstream; any other threshold is silently dropped.\"),\n property_type: ostrnum(\"Accommodation type by name, or a raw numeric Booking accommodation-type id (>= 1). Accepted values: 'apartments', 'hostels', 'hotels', 'motels', 'resorts', 'bed_and_breakfasts', 'villas', 'campgrounds', 'vacation_homes', 'lodges', 'homestays'.\"),\n free_cancellation: obool(\"Only properties offering free cancellation.\"),\n no_prepayment: obool(\"Only properties that take no prepayment.\"),\n breakfast_included: obool(\"Only rates that include breakfast.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout: a lone checkin is ignored and Booking prices a default range of its own.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Booking prices off the proxy exit and identical requests disagree.\"),\n }),\n (i) => client.booking.search(i as SdkOpts<typeof client.booking.search>)\n ),\n tool(\n \"BOOKING_HOTEL\",\n \"Scavio Booking.com Hotel\",\n \"One Booking.com property in full: rooms and rate plans, facilities, house rules, check-in windows, policies, images, location and review scores, priced for the stay asked for. Chaining the `url` a search row returns is cheaper than a bare slug. Costs 1 credit.\",\n z.object({\n hotel: str(\"Booking.com property URL or the bare page slug (1-500 characters); query params are discarded.\"),\n country_code: ostr(\"Two-letter country code for the property page (default 'us'). Only consulted for a bare slug, where a wrong one is a real, BILLED 404.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout; omitting both prices a two-night range Booking chose, echoed back in the response.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Booking prices off the proxy exit and identical requests disagree.\"),\n }),\n (i) => client.booking.hotel(i as SdkOpts<typeof client.booking.hotel>)\n ),\n tool(\n \"BOOKING_REVIEWS\",\n \"Scavio Booking.com Reviews\",\n \"Booking.com guest reviews for a property with the score breakdown by category and Booking's own praise/complaint summary. No page param: total_count is the whole review history, count is what this response holds. Costs 1 credit.\",\n z.object({\n hotel: str(\"Booking.com property URL or the bare page slug (1-500 characters); query params are discarded.\"),\n country_code: ostr(\"Two-letter country code for the property page (default 'us'). Only consulted for a bare slug, where a wrong one is a real, BILLED 404.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout; it prices the stay the review page is rendered for.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD').\"),\n }),\n (i) => client.booking.reviews(i as SdkOpts<typeof client.booking.reviews>)\n )\n );\n }\n\n // Tripadvisor is keyed by geo_id + location_id: resolve a name with\n // TRIPADVISOR_LOCATIONS first, or nothing else on the platform is reachable.\n if (all || enableTripadvisor) {\n tools.push(\n tool(\n \"TRIPADVISOR_LOCATIONS\",\n \"Scavio Tripadvisor Locations\",\n \"START HERE: resolve a place or business NAME to the TripAdvisor geo_id / location_id pair every other TripAdvisor endpoint is keyed by. Up to 20 rows. Costs 2 credits.\",\n z.object({\n query: str(\"Place or business name to resolve (1-120 characters).\"),\n limit: onum(\"Rows to return, 1-20 (default 12). Sizes the response only; there is no paging here.\"),\n }),\n (i) => client.tripadvisor.locations(i as SdkOpts<typeof client.tripadvisor.locations>)\n ),\n tool(\n \"TRIPADVISOR_SEARCH\",\n \"Scavio Tripadvisor Search\",\n \"Restaurants, hotels or attractions in a TripAdvisor geo, TripAdvisor-ranked: rating, review count, price band, address, coordinates, phone, hours, Travelers' Choice badge; each row carries the location_id + geo_id pair. 30 locations per page. Provide geo_id or url. Costs 2 credits.\",\n z.object({\n geo_id: ostr(\"TripAdvisor geo id (1-500 characters): 30196, g30196, or a URL carrying one. Required unless url is given.\"),\n category: ostr(\"Listing family to search (default 'restaurants'). Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n page: onum(\"Results page, 1-based. 30 locations per page; a page beyond the last is a 404, not an empty result.\"),\n url: ostr(\"Full tripadvisor.com listing URL (1-500 characters), as an alternative to geo_id; country sites are accepted.\"),\n }),\n (i) => client.tripadvisor.search(i as SdkOpts<typeof client.tripadvisor.search>)\n ),\n tool(\n \"TRIPADVISOR_LOCATION\",\n \"Scavio Tripadvisor Location\",\n \"One TripAdvisor location in full: rating, review histogram and per-aspect sub-ratings, city ranking, price band, cuisines, amenities, address, coordinates, contact, photos, and the FIRST PAGE OF REVIEWS. Provide location_id or url. Costs 2 credits.\",\n z.object({\n location_id: ostr(\"TripAdvisor location id (1-500 characters): 1899234, d1899234, or a full _Review URL. Required unless url is given.\"),\n geo_id: ostr(\"Geo the location sits in; required when location_id is a bare d-id.\"),\n category: ostr(\"Location family (default 'restaurants'); match the location's own type. Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n url: ostr(\"Full tripadvisor.com _Review URL (1-500 characters), as an alternative to location_id.\"),\n }),\n (i) => client.tripadvisor.location(i as SdkOpts<typeof client.tripadvisor.location>)\n ),\n tool(\n \"TRIPADVISOR_REVIEWS\",\n \"Scavio Tripadvisor Reviews\",\n \"A page of TripAdvisor reviews: rating, trip date and type, reviewer home town and contribution count, management response. Page 1 already rides along in location(), so use this to page PAST it; consecutive pages can repeat one review at the boundary, so de-duplicate on review_id. Provide location_id or url. Costs 2 credits.\",\n z.object({\n location_id: ostr(\"TripAdvisor location id (1-500 characters): 1899234, d1899234, or a full _Review URL. Required unless url is given.\"),\n geo_id: ostr(\"Geo the location sits in; required when location_id is a bare d-id.\"),\n category: ostr(\"Location family (default 'restaurants'). It sets the page size, so it must match the location's own type on any page past the first. Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n url: ostr(\"Full tripadvisor.com _Review URL (1-500 characters), as an alternative to location_id.\"),\n page: onum(\"Reviews page, 1-based. 15 per page for restaurants, 10 for hotels and attractions; past the last page is a 404.\"),\n }),\n (i) => client.tripadvisor.reviews(i as SdkOpts<typeof client.tripadvisor.reviews>)\n )\n );\n }\n\n if (all || enableIndeed) {\n tools.push(\n tool(\n \"INDEED_SEARCH\",\n \"Scavio Indeed Search\",\n \"Indeed job postings: title, employer, rating, location, salary range, job type, benefits, posting age, apply route. 10 postings per page. Provide query or location - a location-only search (every posting in a metro) is valid. Costs 2 credits.\",\n z.object({\n query: ostr(\"Job title, keywords or employer (1-500 characters). Required unless location is given.\"),\n location: ostr(\"City and state, postal code, state, country, or 'Remote' (1-200 characters). Valid on its own with no query.\"),\n page: onum(\"Results page, 1-based. 10 postings per page, 1 call each.\"),\n radius: onum(\"Search radius in miles around location. Closed set: Indeed IGNORES any other value and returns the unfiltered set. Upstream default 50. Accepted values: 0, 5, 10, 15, 25, 35, 50, 100.\"),\n max_age_days: onum(\"Maximum posting age in days. Closed set: Indeed IGNORES any other value and returns postings of every age. Accepted values: 1, 3, 7, 14.\"),\n job_type: ostr(\"Employment type filter. Accepted values: 'full_time', 'part_time', 'contract', 'temporary', 'internship'.\"),\n min_salary: onum(\"Minimum annual salary, >= 0. Filters on INDEED'S OWN ESTIMATE for the role, not a posted figure, so postings publishing no salary still match.\"),\n remote: obool(\"Remote postings only.\"),\n }),\n (i) => client.indeed.search(i as SdkOpts<typeof client.indeed.search>)\n ),\n tool(\n \"INDEED_JOB\",\n \"Scavio Indeed Job\",\n \"One Indeed posting in full: description text and HTML, structured salary, employment types, benefits, geocoded address, employer rating, applicant count, original ATS link. An unknown job key is a real 404 that is still billed. Costs 2 credits.\",\n z.object({\n job_id: str(\"16-hex Indeed job key, or any indeed.com URL carrying jk= (/viewjob, /rc/clk, /pagead/clk).\"),\n }),\n (i) => client.indeed.job(i as SdkOpts<typeof client.indeed.job>)\n ),\n tool(\n \"INDEED_COMPANY\",\n \"Scavio Indeed Company\",\n \"Indeed employer profile: description, industry, HQ, size, revenue, CEO approval, overall and per-category ratings, reported salaries, open roles, locations. An unknown slug is a real 404 that is still billed. Costs 2 credits.\",\n z.object({\n company: str(\"indeed.com/cmp/<slug> slug or a full profile URL (1-200 characters); slugs are untidy, e.g. 'Tata-Consultancy-Services-(tcs)'.\"),\n }),\n (i) => client.indeed.company(i as SdkOpts<typeof client.indeed.company>)\n ),\n tool(\n \"INDEED_COMPANY_REVIEWS\",\n \"Scavio Indeed Company Reviews\",\n \"Indeed employee reviews, 20 per page, with per-category ratings, pros/cons, reviewer job title and location, plus aggregated sentiment and topic/location/job-title breakdowns. Costs 2 credits.\",\n z.object({\n company: str(\"indeed.com/cmp/<slug> slug or a full profile URL (1-200 characters).\"),\n page: onum(\"Reviews page, 1-based. 20 reviews per page.\"),\n }),\n (i) => client.indeed.companyReviews(i as SdkOpts<typeof client.indeed.companyReviews>)\n )\n );\n }\n\n if (all || enableAirbnb) {\n tools.push(\n tool(\n \"AIRBNB_SEARCH\",\n \"Scavio Airbnb Search\",\n \"Airbnb stays: stay-total and per-night price with the full discount ledger, rating and review count, bedrooms/beds/baths, coordinates, badges, images, dates_are_defaulted. 18 listings per page; page and cursor are mutually exclusive. Costs 1 credit.\",\n z.object({\n location: str(\"City, region, ZIP, or a pasted airbnb.com/s/ URL (1-200 characters). An unresolvable location is a 404.\"),\n check_in: ostr(\"Check-in date, YYYY-MM-DD. Must be sent with check_out; omitting both defaults to +30 days and flags dates_are_defaulted in the response.\"),\n check_out: ostr(\"Check-out date, YYYY-MM-DD. Must be later than check_in; defaults to check_in plus 5 nights when omitted.\"),\n adults: onum(\"Adult guests, >= 1.\"),\n children: onum(\"Children aged 2-12, >= 0.\"),\n infants: onum(\"Infants under 2, >= 0.\"),\n pets: onum(\"Pets, >= 0.\"),\n min_price: onum(\"Minimum price for the WHOLE STAY in `currency`, not per night, >= 0. Must not exceed max_price.\"),\n max_price: onum(\"Maximum price for the WHOLE STAY in `currency`, not per night, >= 0.\"),\n room_type: ostr(\"Room type. Validated before the scrape, because an unrecognised value returns the UNFILTERED set under a 200. Accepted values: 'entire_home', 'private_room', 'shared_room', 'hotel_room'.\"),\n min_bedrooms: onum(\"Minimum bedrooms, >= 0.\"),\n min_beds: onum(\"Minimum beds, >= 0.\"),\n min_bathrooms: onum(\"Minimum bathrooms, >= 0.\"),\n superhost: obool(\"Superhost listings only.\"),\n instant_book: obool(\"Instant Book listings only.\"),\n guest_favorite: obool(\"Guest Favorite listings only.\"),\n free_cancellation: obool(\"Listings with free cancellation only.\"),\n amenities: ostr(\"Comma-separated amenities (1-200 characters): wifi, air_conditioning, pool, kitchen, free_parking, washer, self_check_in, tv, or raw numeric Airbnb amenity ids. An unrecognised NAME is rejected before the scrape.\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Airbnb prices off the proxy exit and identical requests disagree.\"),\n page: onum(\"Results page, 1-based. 18 listings per page. Cannot be combined with cursor.\"),\n cursor: ostr(\"next_cursor from a previous response (1-500 characters); wins over page, so sending both is rejected.\"),\n }),\n (i) => client.airbnb.search(i as SdkOpts<typeof client.airbnb.search>)\n ),\n tool(\n \"AIRBNB_LISTING\",\n \"Scavio Airbnb Listing\",\n \"One Airbnb listing in full: description, property/room type, capacity and room counts, the complete grouped amenity list (including what the place does NOT have), host profile and stats, house rules, cancellation policy, sleeping arrangements, photo tour and the RATING BREAKDOWN. Carries NO nightly price - prices are search-only. Costs 1 credit.\",\n z.object({\n listing_id: str(\"Airbnb listing id or a full /rooms/ URL (1-500 characters); query params are discarded, since they carry someone else's dates.\"),\n check_in: ostr(\"Check-in date, YYYY-MM-DD. Must be sent with check_out. Does not produce a price: the room page has no nightly rate.\"),\n check_out: ostr(\"Check-out date, YYYY-MM-DD. Must be later than check_in and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1.\"),\n children: onum(\"Children aged 2-12, >= 0.\"),\n infants: onum(\"Infants under 2, >= 0.\"),\n pets: onum(\"Pets, >= 0.\"),\n currency: ostr(\"ISO 4217 currency, 3 letters (default 'USD').\"),\n }),\n (i) => client.airbnb.listing(i as SdkOpts<typeof client.airbnb.listing>)\n ),\n tool(\n \"AIRBNB_REVIEWS\",\n \"Scavio Airbnb Reviews\",\n \"Airbnb review BODIES with per-review rating, date and reviewer name/photo/location, limit/offset paged at up to 50 per call. `count` is the listing's TOTAL review count, `returned` is how many this page holds. The rating breakdown lives on listing(), not here. Costs 1 credit.\",\n z.object({\n listing_id: str(\"Airbnb listing id or a full /rooms/ URL (1-500 characters).\"),\n currency: ostr(\"ISO 4217 currency, 3 letters (default 'USD').\"),\n limit: onum(\"Reviews to return, 1-50 (default 30). Upstream returns a fixed 7 when no explicit limit is sent.\"),\n offset: onum(\"Reviews to skip before this page, >= 0 (default 0).\"),\n }),\n (i) => client.airbnb.reviews(i as SdkOpts<typeof client.airbnb.reviews>)\n )\n );\n }\n\n // Glassdoor is keyed by employer_id: resolve a name with GLASSDOOR_COMPANIES first.\n if (all || enableGlassdoor) {\n tools.push(\n tool(\n \"GLASSDOOR_COMPANIES\",\n \"Scavio Glassdoor Companies\",\n \"START HERE. Resolve a company NAME to the employer_id every other Glassdoor method is keyed by, ranked by Glassdoor and de-duplicated. Costs 1 credit.\",\n z.object({\n query: str(\"Company name to resolve (1-120 characters).\"),\n }),\n (i) => client.glassdoor.companies(i as SdkOpts<typeof client.glassdoor.companies>)\n ),\n tool(\n \"GLASSDOOR_COMPANY\",\n \"Scavio Glassdoor Company\",\n \"Glassdoor employer profile: description, mission, industry, sector, HQ, size and revenue bands, stock symbol, year founded, overall and per-category ratings, star distribution, CEO approval, awards, FAQ and the five server-rendered reviews. Also returns reviews_url and salaries_url, which reviews() and salaries() accept as url to save a fetch. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters) in any form Glassdoor writes it: '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: the profile resolves on employer_id alone, it is ignored entirely when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters): /Overview/, /Reviews/ or /Salary/. A non-glassdoor.com host is rejected.\"),\n }),\n (i) => client.glassdoor.company(i as SdkOpts<typeof client.glassdoor.company>)\n ),\n tool(\n \"GLASSDOOR_REVIEWS\",\n \"Scavio Glassdoor Reviews\",\n \"Up to THREE full Glassdoor reviews - the cap is Glassdoor's login wall - with per-axis scores, pros, cons, advice, job title, location, employment status and employer response, plus complete rating statistics, star distribution, aggregate pro/con highlight terms and per-job-title review counts. There is no page param: move the window with category and employment_status. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters): '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected. Addressing by id costs two upstream fetches; the customer price is unchanged.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: ignored when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters). Pass back reviews_url from company() to skip the resolve fetch. A non-glassdoor.com host is rejected.\"),\n category: ostr(\"Restrict to reviews Glassdoor files under one topic. Closed enum: Glassdoor IGNORES an unknown value and serves the unfiltered set under a 200. Read filtered_review_count on the response to see how many match. Accepted values: 'career_development', 'compensation', 'culture', 'diversity_and_inclusion', 'management', 'work_life_balance'.\"),\n employment_status: ostr(\"Restrict to one kind of employment. Closed enum for the same reason as category; FREELANCE is deliberately absent because it was never confirmed to change the result set. Accepted values: 'full_time', 'part_time', 'contract', 'intern'.\"),\n }),\n (i) => client.glassdoor.reviews(i as SdkOpts<typeof client.glassdoor.reviews>)\n ),\n tool(\n \"GLASSDOOR_SALARIES\",\n \"Scavio Glassdoor Salaries\",\n \"Glassdoor salaries by job title, 10 titles per page: base-pay and total-pay percentiles P10-P90 with medians called out, sample counts, currency, pay period and last-reported date. The figures are Glassdoor's ESTIMATES for the title, not individual reported salaries. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters): '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected. Addressing by id costs two upstream fetches; the customer price is unchanged.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: ignored when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters). Pass back salaries_url from company() to skip the resolve fetch. A non-glassdoor.com host is rejected.\"),\n page: onum(\"Results page, 1-based. Ten job titles per page; page_count on the response is how many pages exist.\"),\n }),\n (i) => client.glassdoor.salaries(i as SdkOpts<typeof client.glassdoor.salaries>)\n )\n );\n }\n\n if (all || enableYelp) {\n tools.push(\n tool(\n \"YELP_SEARCH\",\n \"Scavio Yelp Search\",\n \"Businesses in Yelp's ranked order: rating, review count, price band, categories, address, contact rails, hours, photos and a review snippet; every row carries both business_id and alias. Yelp fixes the page size at 10. Provide term and location, or url. Costs 2 credits.\",\n z.object({\n term: ostr(\"What to look for (1-200 characters): a category ('plumbers'), a dish, or a business name. Required together with location unless url is given.\"),\n location: ostr(\"Where to look (1-200 characters): city and region, a full address, or a postcode. Effectively required - Yelp geolocates a location-less search off the proxy exit, so the same request answers about a different metro run to run.\"),\n page: onum(\"Results page, 1-based. Yelp fixes the page size at 10.\"),\n sort: ostr(\"Result ordering (upstream default 'recommended'). Closed enum: Yelp IGNORES an unrecognised sortby and serves default ranking under a 200, billing a premium scrape for a sort that never ran. Accepted values: 'recommended', 'rating', 'review_count'.\"),\n price: oarrnum(\"Price bands to include, 1 ($) to 4 ($$$$); 1-4 values, combined freely - [1, 2] means $ or $$. Accepted values: 1, 2, 3, 4.\"),\n open_now: obool(\"Only businesses open at the moment of the request.\"),\n attributes: oarrstr(\"Raw Yelp filter aliases, max 20, each 1-100 characters ('RestaurantsDelivery', 'GoodForKids', 'WheelchairAccessible'). A deliberate PASSTHROUGH, not an enum - Yelp's vocabulary runs to ~117 values per vertical and an alias it does not know is ignored upstream, returning unfiltered results.\"),\n url: ostr(\"A full yelp.com/search URL (1-1000 characters) as an alternative to term + location; the query, offset and sort are read out of it and the URL is rebuilt.\"),\n }),\n (i) => client.yelp.search(i as SdkOpts<typeof client.yelp.search>)\n ),\n tool(\n \"YELP_BUSINESS\",\n \"Scavio Yelp Business\",\n \"One business in full: rating and per-star histogram, review count, price band, categories, address and coordinates, phone, website and menu links, hours and holidays, amenities, photos and videos, popular items, health inspections, Q&A, licences and claim status - plus the first page of reviews at no extra cost. Provide business_id or url. Costs 2 credits.\",\n z.object({\n business_id: ostr(\"A Yelp business alias ('desnudo-coffee-austin-2'), its opaque encid, or any yelp.com/biz URL carrying one (1-500 characters). Search rows return both id forms.\"),\n url: ostr(\"A full yelp.com/biz URL (1-1000 characters) as an alternative to business_id.\"),\n }),\n (i) => client.yelp.business(i as SdkOpts<typeof client.yelp.business>)\n ),\n tool(\n \"YELP_REVIEWS\",\n \"Scavio Yelp Reviews\",\n \"A page of reviews: rating, full text, language, author profile and expertise counts, attached photos, reaction counts and owner response. 10 per page. PAGE 1 IS REDUNDANT - it re-fetches the document business() already returned - so start at page 2. Provide business_id or url. Costs 2 credits.\",\n z.object({\n business_id: ostr(\"A Yelp business alias ('desnudo-coffee-austin-2'), its opaque encid, or any yelp.com/biz URL carrying one (1-500 characters).\"),\n url: ostr(\"A full yelp.com/biz URL (1-1000 characters) as an alternative to business_id.\"),\n page: onum(\"Reviews page, 1-based, 10 per page. Page 1 duplicates the reviews business() already returned and costs another 2 credits - start at 2. A page past the last review is a 404, not an empty result.\"),\n sort: ostr(\"Review ordering (upstream default 'relevance'). Closed enum: Yelp IGNORES an unrecognised value and serves default ranking under a billed 200. Accepted values: 'relevance', 'newest', 'oldest', 'rating_high', 'rating_low', 'elites'.\"),\n rating: onum(\"Only reviews at this star rating, 1-5. Changes filtered_review_count on the response, not review_count. Accepted values: 1, 2, 3, 4, 5.\"),\n }),\n (i) => client.yelp.reviews(i as SdkOpts<typeof client.yelp.reviews>)\n )\n );\n }\n\n if (all || enableAppStore) {\n tools.push(\n tool(\n \"APP_STORE_SEARCH\",\n \"Scavio App Store Search\",\n \"Search the App Store and get up to 200 fully-shaped app rows - the same 43-field row as app() - so a search doubles as a bulk metadata fetch and as a publisher lookup. NO PAGINATION: raise limit, there is no second page. Costs 1 credit.\",\n z.object({\n term: str(\"What to search for (1-500 characters). Apple matches an app name, a keyword OR a publisher name, so searching a developer returns their catalogue.\"),\n limit: onum(\"Apps to return, 1-200 (default 25). The ONLY lever on result volume: the search API has no pagination and every offset spelling is silently ignored.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'); decides price, currency, localised title and whether the app is sold there at all. Anything that is not exactly two letters is rejected with a free 400.\"),\n entity: ostr(\"Which catalogue to search: iPhone/iPad apps ('software', the default), iPad apps, or Mac App Store apps. These are separate stores, not a filter - Mac rows carry no iPad/Apple TV screenshots, advisories, features, supported devices or Game Center flag, returning them empty rather than absent. Accepted values: 'software', 'ipad_software', 'mac_software'.\"),\n lang: ostr(\"Listing text language as a five-letter code ('en_us', 'ja_jp'); any other shape is rejected. Independent of country: the storefront sets the price, this sets the words.\"),\n }),\n (i) => client.appStore.search(i as SdkOpts<typeof client.appStore.search>)\n ),\n tool(\n \"APP_STORE_APP\",\n \"Scavio App Store App\",\n \"Full App Store listing: title, description, developer and seller identity, price and currency, all-time and current-version ratings, version and release notes, genres, content rating and advisories, icons at three sizes, screenshots, download size, minimum OS, languages, supported devices and the Game Center and VPP flags. Costs 1 credit.\",\n z.object({\n app_id: str(\"App Store id - the digits after 'id' in an apps.apple.com URL - or the app's bundle id ('notion.id', 'com.burbn.instagram'); both resolve to the identical payload. 1-255 characters matching ^[A-Za-z0-9][A-Za-z0-9._-]*$, so a pasted apps.apple.com URL is rejected with a free 400. An id Apple cannot resolve is a billed 404.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'); decides price, currency, localised title and whether the app is sold there at all. Anything that is not exactly two letters is rejected with a free 400.\"),\n }),\n (i) => client.appStore.app(i as SdkOpts<typeof client.appStore.app>)\n ),\n tool(\n \"APP_STORE_REVIEWS\",\n \"Scavio App Store Reviews\",\n \"A page of App Store reviews: star rating, title, full text, author and the APP VERSION the review was written against. 50 per page, hard-stopped at page 10 - 500 reviews per storefront is Apple's anonymous ceiling. This endpoint cannot 404: an unknown id and a real app with no reviews return the same empty feed. Costs 1 credit.\",\n z.object({\n app_id: str(\"App Store id, NUMERIC ONLY - unlike app(), the reviews feed has no bundle-id form.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'). Anything that is not exactly two letters is rejected with a free 400. Ask a different country to reach past the 500-review ceiling.\"),\n page: onum(\"Reviews page, 1-10, 50 reviews each (default 1). Apple hard-stops at page 10.\"),\n sort: ostr(\"Review ordering (default 'most_recent'). The choice decides whether the vote fields mean anything: under most_recent almost every review is too new to have been voted on and returns zeroes, while most_helpful returns them densely populated.\"),\n }),\n (i) => client.appStore.reviews(i as SdkOpts<typeof client.appStore.reviews>)\n )\n );\n }\n\n if (all || enableGooglePlay) {\n tools.push(\n tool(\n \"GOOGLE_PLAY_SEARCH\",\n \"Scavio Google Play Search\",\n \"Ranked Google Play apps: package name, title, developer, rating, install count, price and IAP range, content rating, icon and screenshots. A branded query returns the hero card as result 1 in the same row shape, plus Play's related-query rail. NO PAGINATION - one shelf of about 30 apps. Costs 2 credits.\",\n z.object({\n query: str(\"What to search the store for (1-200 characters): an app name, a publisher, or a category phrase. Apps only - games are folded into the apps vertical, but books and films use a different card shape and are not covered.\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings: at hl=pt-BR the title, description, install formatting and content rating all move with it. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.search(i as SdkOpts<typeof client.googlePlay.search>)\n ),\n tool(\n \"GOOGLE_PLAY_APP\",\n \"Scavio Google Play App\",\n \"Full Google Play store listing: installs including the REAL count Play publishes but never renders, rating and star histogram, description, developer identity and legal contact, price and IAPs, categories and gameplay tags, screenshots and trailer, version and Android requirement, release and update dates, changelog, the full permission tree, the Data safety table, the 20 server-rendered reviews and the similar-apps and more-by-developer rails. Costs 2 credits.\",\n z.object({\n app_id: str(\"Android package name ('com.spotify.music') or any play.google.com URL carrying one in its id param (1-500 characters).\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings: title, description, install formatting and content rating all move with it. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.app(i as SdkOpts<typeof client.googlePlay.app>)\n ),\n tool(\n \"GOOGLE_PLAY_REVIEWS\",\n \"Scavio Google Play Reviews\",\n \"A page of Google Play reviews: star score, full text, author, thumbs-up count, developer reply and the APP VERSION the reviewer was running. Paged by cursor, up to 200 per call. app() already returns the 20 reviews Play server-renders; use this to page past them or sort differently. Costs 2 credits.\",\n z.object({\n app_id: str(\"Android package name ('com.spotify.music') or any play.google.com URL carrying one in its id param (1-500 characters).\"),\n sort: ostr(\"Review ordering (default 'newest'). Closed enum. The cursor encodes the sort, so keep this identical when paging. Accepted values: 'relevance', 'newest', 'rating'.\"),\n count: onum(\"Reviews to return, 1-200 (default 50); 200 is our cap, not Play's. Play honours more, but a single page that large is megabytes for one credit - page with cursor instead.\"),\n cursor: ostr(\"Continuation token from a prior response's next_cursor (1-4000 characters). Opaque and SINGLE-USE, and it encodes the sort as well as the position - send it back with the SAME sort it came from. A cursor past the last review is a 404, not an empty page.\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.reviews(i as SdkOpts<typeof client.googlePlay.reviews>)\n )\n );\n }\n\n // SEC EDGAR is keyed by CIK: resolve a ticker with SEC_LOOKUP first.\n if (all || enableSec) {\n tools.push(\n tool(\n \"SEC_LOOKUP\",\n \"Scavio SEC Lookup\",\n \"START HERE. Resolve a company name or ticker (AAPL) to the CIK (0000320193) every other SEC EDGAR endpoint is keyed by. Up to 100 rows, tiered by match quality. Costs 1 credit.\",\n z.object({\n query: str(\"Ticker ('AAPL', 'BRK.B'), company name, or a fragment of one (1-200 characters); each row carries its match tier as 'match'.\"),\n limit: onum(\"Rows to return, 1-100. Defaults to 10. Sizes the response; it is not a page param.\"),\n exchange: ostr(\"Restrict to one listing venue; matched case-insensitively, so 'Nasdaq' also works. Filers the SEC lists with no exchange at all are excluded by any value. Accepted values: 'NASDAQ', 'NYSE', 'OTC', 'CBOE'.\"),\n }),\n (i) => client.sec.lookup(i as SdkOpts<typeof client.sec.lookup>)\n ),\n tool(\n \"SEC_COMPANY\",\n \"Scavio SEC Company\",\n \"SEC filer profile: legal and former names, SIC industry, filer category, EIN, LEI, state of incorporation, fiscal year end, addresses, every ticker with its exchange, and a preview of its 10 most recent filings. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK in any spelling (1-20 characters): 320193, 0000320193 or CIK0000320193. A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), dotted or dashed (BRK.B / BRK-B). Wins over cik when both are given.\"),\n }),\n (i) => client.sec.company(i as SdkOpts<typeof client.sec.company>)\n ),\n tool(\n \"SEC_FILINGS\",\n \"Scavio SEC Filings\",\n \"A page of one filer's filings: accession number, form and root form, filing and period dates, 8-K item codes, direct links to the primary document, filing index and attachment directory. Up to 500 per page. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n form: ostrarr(\"Form types to keep: '10-K', ['10-K', '10-Q'] or the comma-joined '10-K,8-K'; each value 1-50 characters, at most 25 values. Matched against the form AND its root form, so 10-K also returns 10-K/A amendments; ask for '10-K/A' to get only amendments.\"),\n date_from: ostr(\"Earliest filing date, inclusive (YYYY-MM-DD).\"),\n date_to: ostr(\"Latest filing date, inclusive (YYYY-MM-DD).\"),\n page: onum(\"Results page, 1-based; page size is whatever limit is set to. No upper bound.\"),\n limit: onum(\"Filings per page, 1-500. Defaults to 50.\"),\n include_history: obool(\"Also fetch the archived filing history beyond EDGAR's 'recent' block, which is not a fixed window (a decade for a quiet filer, about a year for a prolific one). Off by default; at most 10 archived shards are fetched, history_truncated says when a filer had more, and it is still 1 credit.\"),\n }),\n (i) => client.sec.filings(i as SdkOpts<typeof client.sec.filings>)\n ),\n tool(\n \"SEC_CONCEPT\",\n \"Scavio SEC Concept\",\n \"Every value a filer reported for one XBRL concept, newest period first, with the form and filing each number came from. Restatements are kept, not collapsed. Up to 2000 rows. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n concept: str(\"XBRL concept tag, CASE-SENSITIVE (1-120 characters, ^[A-Za-z][A-Za-z0-9]*$): 'NetIncomeLoss' matches, 'netincomeloss' is a 404 upstream. Use facts() to list what a filer actually reports.\"),\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n taxonomy: ostr(\"Reporting taxonomy (1-40 characters, ^[A-Za-z][A-Za-z0-9-]*$): us-gaap, dei, ifrs-full or srt. Defaults to 'us-gaap'.\"),\n unit: ostr(\"Unit of measure to keep (1-40 characters), e.g. 'USD' vs 'USD/shares'.\"),\n form: ostr(\"Form to keep (1-50 characters). EXACT match here, unlike filings(), so '10-K' excludes 10-K/A.\"),\n limit: onum(\"Rows to return, 1-2000. Defaults to 250. Sizes the response; it is not a page param.\"),\n }),\n (i) => client.sec.concept(i as SdkOpts<typeof client.sec.concept>)\n ),\n tool(\n \"SEC_FACTS\",\n \"Scavio SEC Facts\",\n \"The index of every XBRL concept a filer reports - tag, label, description, units and most recent value - across us-gaap, dei and any other taxonomy it uses. This is how you find what to ask concept() for. Up to 2000 rows. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n taxonomy: ostr(\"Restrict to one taxonomy (1-40 characters), e.g. 'us-gaap' or 'dei'.\"),\n query: ostr(\"Case-insensitive substring matched against the tag name and label (1-200 characters).\"),\n limit: onum(\"Rows to return, 1-2000. Defaults to 250. Sizes the response; it is not a page param.\"),\n }),\n (i) => client.sec.facts(i as SdkOpts<typeof client.sec.facts>)\n ),\n tool(\n \"SEC_SEARCH\",\n \"Scavio SEC Search\",\n \"EDGAR full-text search, coverage starting 2001: each hit is the matching DOCUMENT with its URL, form, filing date and filer identity, plus facets by company, form, industry and state. 100 documents per page, last page is 100. Costs 1 credit.\",\n z.object({\n query: ostr(\"Full-text query over filing documents (1-500 characters); a quoted phrase is matched exactly, bare words as a bag of terms. Optional - a cik, ticker, form or date filter on its own is a valid search.\"),\n cik: ostrarr(\"Restrict to one or more filers by CIK: a single value, a list, or a comma-joined string; each 1-20 characters, at most 25 values. Tickers are accepted here too.\"),\n ticker: ostrarr(\"Restrict to one or more filers by ticker symbol: a single value, a list, or a comma-joined string; each 1-20 characters, at most 25 values.\"),\n form: ostrarr(\"Form types to keep: '8-K', ['10-K', '10-Q'] or the comma-joined '10-K,10-Q'; each 1-50 characters, at most 25 values.\"),\n date_from: ostr(\"Earliest filing date, inclusive (YYYY-MM-DD). Full-text coverage starts in 2001.\"),\n date_to: ostr(\"Latest filing date, inclusive (YYYY-MM-DD).\"),\n location: ostrarr(\"Filer business-address locations as EDGAR's own 2-character codes (CA, NY, and its alphanumeric codes for foreign jurisdictions): a single value, a list, or a comma-joined string; at most 25 values.\"),\n sort: ostr(\"Result ordering. Defaults to the index's own relevance ranking. Accepted values: 'relevance', 'newest', 'oldest'.\"),\n page: onum(\"Results page, 1-based, 1-100, 100 documents per page. The SEC's index refuses a result window past 10,000, so 100 is the last page for any query.\"),\n }),\n (i) => client.sec.search(i as SdkOpts<typeof client.sec.search>)\n )\n );\n }\n\n if (all || enableRedfin) {\n tools.push(\n tool(\n \"REDFIN_SEARCH\",\n \"Scavio Redfin Search\",\n \"Redfin listings: price, price per sqft, beds, baths, living area, lot size, year built, coordinates, listing remarks and full photo galleries, for sale, sold or for rent. Up to 350 per page. Provide location, or region_id together with region_type. Costs 1 credit.\",\n z.object({\n location: ostr(\"A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or a bare 5-digit ZIP (1-500 characters). CITY NAMES ARE NOT ACCEPTED - Redfin's own name lookup is blocked to us; use region_id + region_type instead.\"),\n region_id: onum(\"Redfin internal region id (>= 1), used together with region_type. NOT a ZIP code - the two are different number spaces and a ZIP here resolves to another city rather than failing.\"),\n region_type: onum(\"Region kind that region_id belongs to: 1 neighborhood, 2 ZIP, 5 county, 6 city. Must be sent together with region_id or both are ignored in favour of location.\"),\n listing_status: ostr(\"Market to search. Defaults to 'for_sale'. Accepted values: 'for_sale', 'sold', 'for_rent'.\"),\n sold_within_days: onum(\"Sold within the last N days (>= 1). REJECTED unless listing_status='sold', where it defaults to 90.\"),\n page: onum(\"Results page, 1-based; page size is whatever limit is set to. No upper bound.\"),\n limit: onum(\"Listings per page, 1-350. Defaults to 100.\"),\n sort: ostr(\"Result sort order. Defaults to 'recommended', Redfin's own ranking. Accepted values: 'recommended', 'price_low', 'price_high', 'newest', 'oldest', 'sqft_low', 'sqft_high', 'price_per_sqft_low', 'price_per_sqft_high'.\"),\n min_price: onum(\"Minimum price, inclusive (>= 0). Monthly rent when listing_status='for_rent'.\"),\n max_price: onum(\"Maximum price, inclusive (>= 0). Monthly rent when listing_status='for_rent'.\"),\n beds_min: onum(\"Minimum bedrooms (whole number >= 0); fractional values are rejected.\"),\n beds_max: onum(\"Maximum bedrooms (whole number >= 0); fractional values are rejected.\"),\n baths_min: onum(\"Minimum bathrooms (whole number >= 0). WHOLE BATHS ONLY - 1.5 is rejected rather than silently truncated to 1. There is no baths_max.\"),\n sqft_min: onum(\"Minimum living area in square feet (whole number >= 0).\"),\n sqft_max: onum(\"Maximum living area in square feet (whole number >= 0).\"),\n lot_size_min: onum(\"Minimum lot size in square feet (whole number >= 0). There is no lot_size_max.\"),\n year_built_min: onum(\"Earliest year built (whole number >= 0).\"),\n year_built_max: onum(\"Latest year built (whole number >= 0).\"),\n max_hoa: onum(\"Maximum monthly HOA fee in dollars (>= 0).\"),\n property_type: ostr(\"Restrict to one property type. Accepted values: 'house', 'condo', 'townhouse', 'multi_family', 'land', 'other', 'co_op'.\"),\n has_pool: obool(\"Only listings with a pool.\"),\n max_days_on_market: onum(\"Listed at most N days ago (whole number >= 0). Cannot be combined with min_days_on_market - Redfin expresses both bounds through one param.\"),\n min_days_on_market: onum(\"Listed at least N days ago (whole number >= 0). Cannot be combined with max_days_on_market.\"),\n }),\n (i) => client.redfin.search(i as SdkOpts<typeof client.redfin.search>)\n ),\n tool(\n \"REDFIN_PROPERTY\",\n \"Scavio Redfin Property\",\n \"One Redfin listing in full: price, Redfin Estimate and rental estimate, complete MLS fact sheet, price and tax history, listing agents, open houses, schools, climate risk, walkability, sun exposure, monthly weather, permits, zoning, comparable sales and photos. Costs 1 credit.\",\n z.object({\n property_id: str(\"Redfin property id, or any redfin.com listing URL carrying one (1-500 characters).\"),\n }),\n (i) => client.redfin.property(i as SdkOpts<typeof client.redfin.property>)\n ),\n tool(\n \"REDFIN_MARKET\",\n \"Scavio Redfin Market\",\n \"Redfin housing-market stats for a region: median list and sale price, price per sqft, sale-to-list ratio, average offers and days on market, YoY movement, 0-100 compete score, live inventory by property type and by bedroom count, and Redfin agent presence. Provide location, or region_id together with region_type. Costs 1 credit.\",\n z.object({\n location: ostr(\"A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or a bare 5-digit ZIP (1-500 characters). City names are not accepted.\"),\n region_id: onum(\"Redfin internal region id (>= 1), used together with region_type. Not a ZIP code.\"),\n region_type: onum(\"Region kind that region_id belongs to: 1 neighborhood, 2 ZIP, 5 county, 6 city. Must be sent together with region_id or both are ignored in favour of location.\"),\n }),\n (i) => client.redfin.market(i as SdkOpts<typeof client.redfin.market>)\n )\n );\n }\n\n if (all || enableCompaniesHouse) {\n tools.push(\n tool(\n \"COMPANIES_HOUSE_SEARCH\",\n \"Scavio Companies House Search\",\n \"START HERE. Search the UK register by name and get the company_number every other Companies House endpoint is keyed by, plus status, incorporation or dissolution date, registered office and matched former names. 20 per page, last page is 50. Costs 1 credit.\",\n z.object({\n query: str(\"Company name or fragment (1-200 characters, non-blank). Matches CURRENT AND FORMER names.\"),\n page: onum(\"Results page, 1-based, 1-50, 20 results per page. Defaults to 1. The register serves only a 1000-result window per term whatever hit count it prints, and answers page 51 with HTTP 416.\"),\n }),\n (i) => client.companiesHouse.search(i as SdkOpts<typeof client.companiesHouse.search>)\n ),\n tool(\n \"COMPANIES_HOUSE_COMPANY\",\n \"Scavio Companies House Company\",\n \"Full UK register entry: status, type, incorporation and dissolution dates, registered office, SIC codes, previous names, accounts and confirmation-statement due dates with overdue flags, and whether it has charges, insolvency history, officers or UK establishments. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you, so '445790' and 'sc090312' both work. Registry prefixes supported: SC, NI, OC, SO, NC, FC, BR, CE.\"),\n }),\n (i) => client.companiesHouse.company(i as SdkOpts<typeof client.companiesHouse.company>)\n ),\n tool(\n \"COMPANIES_HOUSE_OFFICERS\",\n \"Scavio Companies House Officers\",\n \"UK company officers, current and resigned, 35 per page: name, role, appointment and resignation dates, correspondence address, nationality, country of residence, month-and-year date of birth and identity-verification status. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you.\"),\n page: onum(\"Results page, 1-based, 35 per page. Defaults to 1. No upper bound: past the last page the register answers an ordinary 200 with an empty list, identical to a company with no officers.\"),\n }),\n (i) => client.companiesHouse.officers(i as SdkOpts<typeof client.companiesHouse.officers>)\n ),\n tool(\n \"COMPANIES_HOUSE_FILING_HISTORY\",\n \"Scavio Companies House Filing History\",\n \"UK filings, most recent first: date, filing type code (AA, CS01, SH03), description, register annotations and child documents, and a link to the filed PDF with its page count. A filing the register has not finished processing carries a processing_note instead of a document. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you.\"),\n page: onum(\"Results page, 1-based. Defaults to 1. No upper bound: past the last page the register answers an ordinary 200 with an empty list.\"),\n }),\n (i) => client.companiesHouse.filingHistory(i as SdkOpts<typeof client.companiesHouse.filingHistory>)\n )\n );\n }\n\n if (all || enableG2) {\n tools.push(\n tool(\n \"G2_SEARCH\",\n \"Scavio G2 Search\",\n \"Search G2, the B2B software review site, for products: star rating, review count, vendor, categories, seller description and logo, with product_id and slug on every row. Up to 100 results per page (server default 20) and page-paginated; total_results is G2's Products-tab headline and caps at 10000, while total_by_type splits the query across products, sellers, categories and discussions. Provide query or url. Costs 5 credits.\",\n z.object({\n query: ostr(\"Search term (1-200 characters). Provide this or url.\"),\n page: onum(\"1-based page number; page size follows limit (server default 20). G2 keeps paginating well past its own widget's page links.\"),\n limit: onum(\"Results per page (1-100; server default 20). The 100 ceiling is ours, to keep a single request inside the 60s deadline; G2 itself paginates at any size.\"),\n sort: ostr(\"Result sort order (server default 'relevance'). Closed enum: G2 silently accepts an unknown sort and answers 200 with an unstated ordering. Accepted values: 'relevance', 'popular', 'alphabetical', 'rating'.\"),\n rating: onum(\"Only products at or above this star rating (1-5, sent as an integer). Omit for no rating floor. Accepted values: 1, 2, 3, 4, 5.\"),\n url: ostr(\"Full g2.com/search URL, as an alternative to query (1-1000 characters; the host is checked by the transport).\"),\n }),\n (i) => client.g2.search(i as SdkOpts<typeof client.g2.search>)\n ),\n tool(\n \"G2_PRODUCT\",\n \"Scavio G2 Product\",\n \"Full G2 product profile: rating with per-star histogram, review count, vendor, description and seller website, pricing editions with parsed amounts, feature groups, categories and breadcrumbs, supported languages, integrations, alternatives, head-to-head comparisons, media, community discussions and G2's AI-derived pros and cons. Carries NO review text at all -- G2 loads review bodies in a separate frame, so call reviews() for those. Provide product_id or url. Costs 5 credits.\",\n z.object({\n product_id: ostr(\"G2 product slug ('notion') or the numeric G2 id ('82623') as a string (1-200 characters); both resolve on the same upstream path.\"),\n url: ostr(\"Full g2.com product URL, as an alternative to product_id (1-1000 characters).\"),\n }),\n (i) => client.g2.product(i as SdkOpts<typeof client.g2.product>)\n ),\n tool(\n \"G2_REVIEWS\",\n \"Scavio G2 Reviews\",\n \"A page of G2 reviews: rating, title, likes and dislikes, problems solved, reviewer job title, industry and company size, validated and incentivized flags -- plus what the profile page has no form of: exact per-star counts, pros and cons with per-theme counts, and company-size, role, industry, region and category facets with counts. Fixed at 10 reviews per page and paginates well past the 10 pages G2's own widget links to. Provide product_id or url. Costs 5 credits.\",\n z.object({\n product_id: ostr(\"G2 product slug or numeric G2 id as a string (1-200 characters).\"),\n url: ostr(\"Full g2.com reviews URL, as an alternative to product_id (1-1000 characters).\"),\n page: onum(\"1-based page number; fixed at 10 reviews per page.\"),\n sort: ostr(\"Review sort order (server default 'relevance'). Closed enum: an unknown sort is silently accepted upstream and never runs. Accepted values: 'relevance', 'newest', 'most_helpful', 'rating_high', 'rating_low'.\"),\n rating: onum(\"Only reviews in this star bucket (1-5, sent as an integer). Buckets are half- star-inclusive: 1 returns 0, 0.5 and 1-star reviews. Accepted values: 1, 2, 3, 4, 5.\"),\n company_size: ostr(\"Reviewer company size: small_business is 50 employees or fewer, mid_market 51-1000, enterprise over 1000. Closed enum -- an unknown value matches nothing and returns a billed 'Reviews (0)'.\"),\n role: ostr(\"Reviewer role. Closed enum -- an unknown value matches nothing rather than erroring. Accepted values: 'user', 'administrator', 'executive_sponsor', 'internal_consultant', 'consultant', 'agency', 'industry_analyst'.\"),\n region: ostr(\"Reviewer region. Closed enum -- an unknown value matches nothing rather than erroring. Accepted values: 'north_america', 'europe', 'asia', 'latin_america', 'anz', 'middle_east', 'africa'.\"),\n query: ostr(\"Full-text search within this product's reviews (1-200 characters); narrows the review list AND every facet count.\"),\n }),\n (i) => client.g2.reviews(i as SdkOpts<typeof client.g2.reviews>)\n )\n );\n }\n\n if (all || enableCapterra) {\n tools.push(\n tool(\n \"CAPTERRA_SEARCH\",\n \"Scavio Capterra Search\",\n \"Search Capterra, the B2B software review site: 20 ranked products with name, vendor description, rating, review count, logo and paid-placement flag, each row carrying product_id and slug. The result set is fixed at 20 and does NOT paginate -- Capterra serves identical rows for page 2, so there is deliberately no page parameter. Provide query or url. Costs 2 credits.\",\n z.object({\n query: ostr(\"Search term (1-200 characters). Required in practice: a term-less Capterra search serves a fixed popular-products list unrelated to the caller.\"),\n url: ostr(\"Full capterra.com search URL, as an alternative to query (1-1000 characters; the transport also accepts capterra.co.uk and capterra.com.br hosts).\"),\n }),\n (i) => client.capterra.search(i as SdkOpts<typeof client.capterra.search>)\n ),\n tool(\n \"CAPTERRA_PRODUCT\",\n \"Scavio Capterra Product\",\n \"Full Capterra profile: rating with per-star histogram and the four scored criteria, likelihood to recommend, review sentiment and topics, the complete pricing table with every plan and its features, every rated feature and integration, AI-derived pros and cons with the quoted review, FAQs, screenshots, badges and awards, competitor comparisons and alternatives, and the buyer profile by company size, industry and job function -- PLUS the 25 most recent reviews at no extra cost. vendor is always null here: Capterra does not publish it as structured data on the product page. Provide product_id or url. Costs 2 credits.\",\n z.object({\n product_id: ostr(\"The number in a Capterra product path such as /p/186596/Notion/ (1-50 characters). Must be a STRING -- a JSON number is rejected.\"),\n slug: ostr(\"Product slug (1-200 characters). Cosmetic on this endpoint -- a wrong slug still returns the right profile -- but load-bearing on reviews().\"),\n url: ostr(\"Full Capterra product URL, as an alternative to product_id (1-1000 characters).\"),\n }),\n (i) => client.capterra.product(i as SdkOpts<typeof client.capterra.product>)\n ),\n tool(\n \"CAPTERRA_REVIEWS\",\n \"Scavio Capterra Reviews\",\n \"A page of Capterra reviews: overall score plus five per-criterion scores, title, pros, cons, advice, usage duration, incentivized flag, alternatives considered and what they switched from, reviewer job title, industry and company size, and the vendor response -- plus a competitor list richer than the profile's, each alternative with its own rating histogram and starting price. 25 reviews per page, capped at page 100. Page 1 already rides along inside product(), so use this to page past it. Provide product_id or url. Costs 2 credits.\",\n z.object({\n product_id: ostr(\"Capterra product id as a string (1-50 characters).\"),\n slug: ostr(\"Product slug (1-200 characters). LOAD-BEARING here: it is case-sensitive upstream and a wrong one silently serves page one under a billed 200. Pass back the slug from search() or product().\"),\n url: ostr(\"Full Capterra reviews URL, as an alternative to product_id (1-1000 characters). Passing back reviews_url from product() is the reliable way to page.\"),\n page: onum(\"1-based page number (1-100); 25 reviews per page. 100 is a hard cap whatever the review count says -- past it Capterra answers 200 with page one.\"),\n }),\n (i) => client.capterra.reviews(i as SdkOpts<typeof client.capterra.reviews>)\n )\n );\n }\n\n // Google Ads Transparency is keyed by advertiser_id: resolve a brand with\n // GOOGLE_ADS_ADVERTISERS first.\n if (all || enableGoogleAds) {\n tools.push(\n tool(\n \"GOOGLE_ADS_ADVERTISERS\",\n \"Scavio Google Ads Advertisers\",\n \"Resolve a brand name or domain to the advertiser_id that search() and creative() are keyed by. Returns two row kinds in one list: 'advertiser' rows carrying the id, verified name, verification country and total ad count as a range, and 'domain' rows carrying a website. A name query returns both kinds; a domain-shaped query returns domains only. Autocomplete-backed, roughly 20 rows per arm, and it does not paginate. Costs 1 credit.\",\n z.object({\n query: str(\"Brand name or domain to resolve (1-200 characters).\"),\n region: ostr(\"ISO 3166-1 alpha-2 country ('US', 'GB', 'DE') or a Google geo criteria id as a string (2-12 characters). Default: no region filter.\"),\n limit: onum(\"Rows per arm (1-20; server default 10). Advertisers and domains are capped separately, so a name query can return up to twice this many rows.\"),\n }),\n (i) => client.googleAds.advertisers(i as SdkOpts<typeof client.googleAds.advertisers>)\n ),\n tool(\n \"GOOGLE_ADS_SEARCH\",\n \"Scavio Google Ads Search\",\n \"Every ad Google Ads Transparency holds for one advertiser: the creative (archived image, rich-media bundle, Google's renderer link, dimensions), advertiser id and name, format, first and last seen dates and days actually run, plus total_ads_min and total_ads_max -- Google publishes the advertiser's ad total as a range, never an exact figure. Up to 100 ads per page (server default 40); paginate by sending next_cursor back as cursor alongside the SAME filters. Provide domain or advertiser_id. Costs 1 credit.\",\n z.object({\n domain: ostr(\"Advertiser website (1-253 characters): bare host, www host or full URL, reduced to the registrable host. The only way to get `domain` back on each row.\"),\n advertiser_id: ostr(\"Google advertiser id, e.g. 'AR16735076323512287233' (3-40 characters). The shape is checked before any request, so a typo costs no credits. Querying by id drops `domain` from every row.\"),\n region: ostr(\"ISO 3166-1 alpha-2 country ('US', 'GB', 'DE') or a Google geo criteria id as a string (2-12 characters). Scopes the deep links on every row, and the same advertiser can share zero creatives between two countries. Default: worldwide.\"),\n format: ostr(\"Creative format. The three sets are disjoint -- an advertiser's text, image and video ads share no creatives. Default: all formats.\"),\n platform: ostr(\"Google surface the ad ran on. Default: all surfaces. Accepted values: 'play', 'maps', 'search', 'shopping', 'youtube'.\"),\n topic: ostr(\"Ad topic (server default 'all'). Accepted values: 'all', 'political'.\"),\n limit: onum(\"Ads per page (1-100; server default 40). 100 is a hard upstream ceiling, not our policy: Google answers a larger request with zero rows rather than an error.\"),\n cursor: ostr(\"next_cursor from the previous response (1-4000 characters), 100 ads per page. Re-send the same filters alongside it; next_cursor is null once exhausted.\"),\n }),\n (i) => client.googleAds.search(i as SdkOpts<typeof client.googleAds.search>)\n ),\n tool(\n \"GOOGLE_ADS_CREATIVE\",\n \"Scavio Google Ads Creative\",\n \"One creative in full, and the only endpoint carrying its history: every size variation of the asset, the impression bucket, the per-region breakdown with first and last shown dates and a per-surface impression split inside each region, the format, Google's category label and the funder disclosure on political ads. Impressions and first_shown are EEA-only (DSA-compelled) and come back null for US creatives, and an impression bucket may carry only a lower or only an upper bound. Costs 1 credit.\",\n z.object({\n advertiser_id: str(\"Google advertiser id, e.g. 'AR16735076323512287233' (3-40 characters).\"),\n creative_id: str(\"Creative id (3-40 characters). It must belong to the advertiser_id sent with it -- the lookup is keyed by the pair and a mismatched pair is a 404.\"),\n }),\n (i) => client.googleAds.creative(i as SdkOpts<typeof client.googleAds.creative>)\n )\n );\n }\n\n // Meta Ad Library is served from /api/v1/meta-ads/* - HYPHENATED. The path is\n // never derived from the namespace key.\n if (all || enableMetaAds) {\n tools.push(\n tool(\n \"META_ADS_SEARCH\",\n \"Scavio Meta Ads Search\",\n \"Search the Meta Ad Library by keyword: 30 ads on page 1 with the full creative -- page name, ad copy, headline, CTA, images and videos, the platforms each ran on and its run dates -- then 10 ads per cursor page, walking has_next_page to the end of the query. total_results caps at 50000 with total_is_capped true, because Meta only reports '>50,000'; never present it as an exact count. Every page costs 1 credit.\",\n z.object({\n query: str(\"Keyword to search the ad library for (1-200 characters).\"),\n country: ostr(\"Ad library country as an exactly 2-character ISO 3166-1 alpha-2 code (server default 'US').\"),\n active_status: ostr(\"Whether the ad is still running (server default 'all'). Accepted values: 'all', 'active', 'inactive'.\"),\n ad_type: ostr(\"Set 'political_and_issue_ads' to expose spend, reach, impressions and the paid-for-by disclosure; commercial ads leave all four null (server default 'all').\"),\n media_type: ostr(\"Creative media filter. Default: no media filter. Accepted values: 'all', 'image', 'video', 'meme', 'image_and_meme', 'none'.\"),\n search_type: ostr(\"How the query is matched (server default 'keyword_unordered'). Accepted values: 'keyword_unordered', 'keyword_exact_phrase'.\"),\n cursor: ostr(\"next_cursor from the previous response: page 1 is 30 ads, every cursor page is 10. The cursor is a self-contained blob, so ALL other filters are ignored when it is present.\"),\n }),\n (i) => client.metaAds.search(i as SdkOpts<typeof client.metaAds.search>)\n ),\n tool(\n \"META_ADS_ADVERTISER\",\n \"Scavio Meta Ads Advertiser\",\n \"Every ad a Facebook Page is running, by numeric page id: 30 ads on page 1 with the same creative detail as search(), then 10 ads per cursor page, walking has_next_page to the end of the advertiser. Every page costs 1 credit.\",\n z.object({\n page_id: str(\"The advertiser's numeric Facebook Page id (3-25 digits, as a string).\"),\n country: ostr(\"Ad library country as an exactly 2-character ISO 3166-1 alpha-2 code (server default 'US').\"),\n active_status: ostr(\"Whether the ad is still running (server default 'all'). Accepted values: 'all', 'active', 'inactive'.\"),\n ad_type: ostr(\"Set 'political_and_issue_ads' to expose spend, reach, impressions and the paid-for-by disclosure; commercial ads leave all four null (server default 'all').\"),\n media_type: ostr(\"Creative media filter. Default: no media filter. Accepted values: 'all', 'image', 'video', 'meme', 'image_and_meme', 'none'.\"),\n cursor: ostr(\"next_cursor from the previous response: page 1 is 30 ads, every cursor page is 10. ALL other filters are ignored when it is present.\"),\n }),\n (i) => client.metaAds.advertiser(i as SdkOpts<typeof client.metaAds.advertiser>)\n ),\n tool(\n \"META_ADS_AD\",\n \"Scavio Meta Ads Ad\",\n \"One Meta ad in full by archive id: creative, advertiser, run dates, the platforms it ran on, and the political disclosure when the ad carries one. Commercial ads leave spend, reach and impressions null. Costs 1 credit.\",\n z.object({\n ad_archive_id: str(\"Meta ad archive id (3-25 digits, as a string).\"),\n }),\n (i) => client.metaAds.ad(i as SdkOpts<typeof client.metaAds.ad>)\n )\n );\n }\n\n // extract is a CORE endpoint, not a platform: the top-level client.extract(),\n // never client.extract.extract(). It is the agent's 'read this page' primitive.\n if (all || enableExtract) {\n tools.push(\n tool(\n \"EXTRACT\",\n \"Scavio Extract\",\n \"Read any URL and get the page back as raw HTML, readability Markdown or plain text: { url, format, mode, content, content_length }. Tier-priced by mode: 'normal' and 'advanced' cost 1 credit, 'ultra' costs 2. Only a successful extraction is billed - a dead link, bot wall or timeout costs nothing.\",\n z.object({\n 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.\"),\n format: ostr(\"Output format: 'html' is the raw page, 'markdown' a readability extraction, 'text' that markdown flattened to plain text (server default 'markdown').\"),\n 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'.\"),\n }),\n (i) => client.extract(i as SdkOpts<typeof client.extract>)\n )\n );\n }\n\n // Website map, crawl and batch. Opt-in: a crawl bills per page.\n if (all || enableCrawl) {\n const crawlStatus: JobStatusFn = (id, q) => client.extract.crawlStatus(id, q);\n const batchStatus: JobStatusFn = (id, q) => client.extract.batchStatus(id, q);\n const readStatus =\n (status: JobStatusFn) =>\n async ({ id, limit, ...q }: z.infer<typeof JOB_STATUS_PARAMS>) =>\n (await status(id, {\n ...(q as JobQuery),\n limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT,\n })) as Record<string, unknown>;\n tools.push(\n tool(\n \"MAP_WEBSITE\",\n \"Scavio Map Website\",\n \"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.\",\n z.object({\n url: str(\"The site to map. A bare host is upgraded to https.\"),\n search: ostr(\"Only return URLs containing every word of this text (case-insensitive).\"),\n 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).\"),\n sitemap: ostr(\"'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone.\"),\n include_subdomains: obool(\"Also return URLs on subdomains of the site (default false).\"),\n include_paths: oarrstr(\"Keep only URLs matching these. \" + JOB_PATHS),\n exclude_paths: oarrstr(\"Drop URLs matching these. \" + JOB_PATHS),\n ignore_query_parameters: obool(\"Treat URLs that differ only by query string as one URL (default true).\"),\n mode: JOB_MODE,\n }),\n async (i) =>\n (await client.extract.map(i as SdkOpts<typeof client.extract.map>)) as unknown as Record<string, unknown>\n ),\n tool(\n \"CRAWL_WEBSITE\",\n \"Scavio Crawl Website\",\n \"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,\n z.object({\n url: str(\"Where the crawl starts. Only pages on the same site are crawled.\"),\n 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.\"),\n max_depth: onum(\"How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page.\"),\n include_paths: oarrstr(\"Crawl only paths matching these. \" + JOB_PATHS),\n exclude_paths: oarrstr(\"Skip paths matching these. \" + JOB_PATHS),\n allow_subdomains: obool(\"Also crawl subdomains of the site (default false).\"),\n ignore_query_parameters: obool(\"Treat URLs that differ only by query string as one page (default true).\"),\n sitemap: ostr(\"'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links.\"),\n format: JOB_FORMAT,\n mode: JOB_MODE,\n wait_seconds: JOB_WAIT,\n limit: JOB_LIMIT,\n include_content: JOB_INCLUDE_CONTENT,\n }),\n (i) =>\n startAndWait(\n (body) => client.extract.crawl(body as SdkOpts<typeof client.extract.crawl>),\n crawlStatus,\n i,\n pollIntervalMs\n )\n ),\n tool(\n \"CRAWL_STATUS\",\n \"Scavio Crawl Status\",\n \"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.\",\n JOB_STATUS_PARAMS,\n readStatus(crawlStatus)\n ),\n tool(\n \"BATCH_EXTRACT\",\n \"Scavio Batch Extract\",\n \"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,\n z.object({\n urls: arrstr(\"The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000.\"),\n format: JOB_FORMAT,\n mode: JOB_MODE,\n wait_seconds: JOB_WAIT,\n limit: JOB_LIMIT,\n include_content: JOB_INCLUDE_CONTENT,\n }),\n (i) =>\n startAndWait(\n (body) => client.extract.batch(body as SdkOpts<typeof client.extract.batch>),\n batchStatus,\n i,\n pollIntervalMs\n )\n ),\n tool(\n \"BATCH_STATUS\",\n \"Scavio Batch Status\",\n \"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.\",\n JOB_STATUS_PARAMS,\n readStatus(batchStatus)\n )\n );\n }\n\n return experimental_createToolkit(\"SCAVIO\", {\n name: \"Scavio\",\n description:\n \"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.\",\n tools,\n });\n}\n\nexport default buildScavioToolkit;\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Scavio tools for Composio.\n *\n * Scavio is a single Search API over 31 platforms - Google, YouTube, Amazon,\n * Walmart, eBay, Target, Home Depot, Reddit, TikTok, TikTok Shop, Instagram, X,\n * LinkedIn, Threads, Kuaishou, Zillow, Redfin, Booking.com, Airbnb, Tripadvisor,\n * Yelp, Indeed, Glassdoor, the Apple App Store, Google Play, SEC EDGAR, Companies\n * House, G2, Capterra, Google Ads Transparency and the Meta Ad Library - plus a\n * top-level extract() that reads any URL as Markdown, plain text or raw HTML.\n * This toolkit exposes every live endpoint of all of them (189 tools), plus five\n * opt-in website tools (map, crawl, batch) behind enableCrawl. Build it\n * with `buildScavioToolkit()` and bind it to a session:\n *\n * import { Composio } from \"@composio/core\";\n * import { buildScavioToolkit } from \"composio-scavio\";\n *\n * const composio = new Composio();\n * const scavio = buildScavioToolkit({ apiKey: process.env.SCAVIO_API_KEY });\n * const session = await composio.create(\"user_1\", {\n * experimental: { customToolkits: [scavio] },\n * });\n * const out = await session.execute(\"LOCAL_SCAVIO_GOOGLE_SEARCH\", { query: \"ai agents\" });\n *\n * Each provider is gated by an `enable*` flag so an agent only sees the tools it\n * needs. The ten original platforms and `extract` are on by default (104 tools);\n * the 21 verticals added in 0.4.0 are OPT-IN, because registering all 189 at once\n * buries the handful an agent actually wants. Pass `all: true` for everything.\n */\nimport {\n experimental_createTool,\n experimental_createToolkit,\n} from \"@composio/core\";\nimport { Scavio } from \"scavio\";\nimport { z } from \"zod\";\n\nexport interface BuildScavioToolkitOptions {\n /** Scavio API key. Falls back to the SCAVIO_API_KEY env var. */\n apiKey?: string;\n enableGoogle?: boolean;\n enableAmazon?: boolean;\n enableWalmart?: boolean;\n enableYoutube?: boolean;\n enableReddit?: boolean;\n enableTiktok?: boolean;\n enableTiktokShop?: boolean;\n enableInstagram?: boolean;\n enableX?: boolean;\n enableLinkedin?: boolean;\n /** The top-level extract() tool: read any URL as Markdown, text or HTML. */\n enableExtract?: boolean;\n // Added in 0.4.0. Opt-in: off unless you ask for them, or pass all.\n enableThreads?: boolean;\n enableKuaishou?: boolean;\n enableEbay?: boolean;\n enableTarget?: boolean;\n enableHomeDepot?: boolean;\n enableZillow?: boolean;\n enableBooking?: boolean;\n enableTripadvisor?: boolean;\n enableIndeed?: boolean;\n enableAirbnb?: boolean;\n enableGlassdoor?: boolean;\n enableYelp?: boolean;\n enableAppStore?: boolean;\n enableGooglePlay?: boolean;\n enableSec?: boolean;\n enableRedfin?: boolean;\n enableCompaniesHouse?: boolean;\n enableG2?: boolean;\n enableCapterra?: boolean;\n enableGoogleAds?: boolean;\n enableMetaAds?: boolean;\n /**\n * Website map, crawl and batch extract (five tools: MAP_WEBSITE, CRAWL_WEBSITE,\n * CRAWL_STATUS, BATCH_EXTRACT, BATCH_STATUS). Opt-in: a crawl bills per page.\n */\n enableCrawl?: boolean;\n /**\n * Milliseconds between progress polls while CRAWL_WEBSITE or BATCH_EXTRACT\n * waits for its job. Default 3000.\n */\n pollIntervalMs?: number;\n /** Register every tool, ignoring the individual flags. */\n all?: boolean;\n}\n\nconst str = (d: string) => z.string().describe(d);\nconst ostr = (d: string) => z.string().optional().describe(d);\nconst onum = (d: string) => z.number().optional().describe(d);\nconst obool = (d: string) => z.boolean().optional().describe(d);\nconst arrstr = (d: string) => z.array(z.string()).describe(d);\nconst oarrstr = (d: string) => z.array(z.string()).optional().describe(d);\nconst oarrnum = (d: string) => z.array(z.number()).optional().describe(d);\n// Booking's property_type is a named enum OR a raw numeric accommodation-type id.\nconst ostrnum = (d: string) => z.union([z.string(), z.number()]).optional().describe(d);\n// SEC filters take a single value, a list, or the comma-joined string.\nconst ostrarr = (d: string) =>\n z.union([z.string(), z.array(z.string())]).optional().describe(d);\n\n// The Scavio SDK types several option fields as string-literal unions (e.g.\n// sort orders, device profiles). Tool schemas keep them as free-form strings so\n// the agent stays flexible and the API validates the value; this extracts an SDK\n// method's options type so a validated input can be handed through unchanged.\ntype SdkOpts<M> = M extends (o: infer O) => unknown ? O : never;\n\n// Google params shared across the v2 family. v1 (/api/v1/google) was retired on\n// 2026-08-04 and answers 410, so none of its vocabulary survives here: no\n// country_code/language/page, no light_request, no search_type. v2 speaks\n// gl/hl/start/google_domain/device natively and they are exposed as-is. `start`\n// in particular is a RESULT OFFSET, not a page number - remapping a 1-based page\n// onto it silently fetches the wrong page, so no such mapping exists.\nconst gl = ostr(\"Country of the search (ISO 3166-1 alpha-2, e.g. 'us', 'gb', 'de').\");\nconst hl = ostr(\"UI language (ISO 639-1, e.g. 'en').\");\nconst googleDomain = ostr(\"Regional Google domain, e.g. 'google.co.uk'.\");\nconst location = ostr(\"Canonical location name, e.g. 'Austin, Texas, United States'. Encoded server-side.\");\nconst device = ostr(\"Device to emulate: 'desktop' or 'mobile'.\");\nconst currency = ostr(\"Currency code (ISO 4217, e.g. 'USD').\");\nconst checkInDate = str(\"Check-in date (YYYY-MM-DD).\");\nconst checkOutDate = str(\"Check-out date (YYYY-MM-DD).\");\n\n// Website map, crawl and batch: the multi-page members of the Extract family.\n//\n// Map answers in one call. Crawl and batch are background jobs: the start tools\n// post the job, then wait up to wait_seconds (default 45, max 300) for it to\n// finish, polling progress without page content, and return the job's status\n// with its first page of results either way. A job still running when the wait\n// ends keeps going server-side; read the rest with the matching status tool.\n// Cancellation, webhooks and idempotency keys are in the SDK, not tools.\nconst JOB_POLL_INTERVAL_MS = 3_000;\nconst JOB_WAIT_DEFAULT_SECONDS = 45;\nconst JOB_WAIT_MAX_SECONDS = 300;\nconst JOB_RESULTS_DEFAULT_LIMIT = 10;\nconst JOB_TERMINAL = new Set([\"completed\", \"failed\", \"cancelled\"]);\n\ntype JobQuery = {\n cursor?: string;\n limit?: number;\n status?: \"succeeded\" | \"failed\" | \"skipped\";\n include_content?: boolean;\n};\ntype JobPayload = { data?: { id?: string; status?: string } } & Record<string, unknown>;\ntype JobStatusFn = (id: string, query: JobQuery) => Promise<unknown>;\n\nconst sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms));\n\n/** Poll a job (content-free) until it finishes or the wait runs out, then read one results page. */\nasync function waitForJob(\n status: JobStatusFn,\n id: string,\n waitSeconds: number,\n pollMs: number,\n query: JobQuery\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + Math.max(0, Math.min(waitSeconds, JOB_WAIT_MAX_SECONDS)) * 1000;\n for (;;) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n await sleep(Math.min(pollMs, remaining));\n const probe = (await status(id, { limit: 1, include_content: false })) as JobPayload;\n if (JOB_TERMINAL.has(String(probe?.data?.status))) break;\n }\n return (await status(id, query)) as Record<string, unknown>;\n}\n\n/** Start a job, then wait for it (bounded). wait_seconds 0 returns the 202 payload. */\nasync function startAndWait(\n start: (body: Record<string, unknown>) => Promise<unknown>,\n status: JobStatusFn,\n input: Record<string, unknown>,\n pollMs: number\n): Promise<Record<string, unknown>> {\n const { wait_seconds, limit, include_content, ...body } = input as Record<string, unknown> & {\n wait_seconds?: number;\n limit?: number;\n include_content?: boolean;\n };\n const created = (await start(body)) as JobPayload;\n const id = created?.data?.id;\n const wait = wait_seconds ?? JOB_WAIT_DEFAULT_SECONDS;\n if (!id || wait <= 0) return created;\n const query: JobQuery = { limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT };\n if (include_content !== undefined) query.include_content = include_content;\n return waitForJob(status, id, wait, pollMs, query);\n}\n\nconst JOB_MODE = ostr(\n \"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'.\"\n);\nconst JOB_PATHS =\n \"Path globs (max 20). '*' matches within one path segment, '**' across segments; a pattern without wildcards matches that path and everything under it. Example: ['/blog/**'].\";\nconst JOB_PRICE =\n \"Billed per SUCCESSFUL page at Extract's price for the mode: 'normal' and 'advanced' 1 credit, 'ultra' 2 credits. Failed and skipped pages are free, and if the balance runs out the job stops cleanly.\";\nconst JOB_FORMAT = ostr(\"Format for each page, as on extract: 'html', 'markdown' or 'text' (server default 'markdown').\");\nconst JOB_WAIT = onum(\n \"Seconds to wait for the job to finish before returning, 0-300 (default 45). 0 returns the job id at once. A job still running when the wait ends keeps going; read it later with its status tool.\"\n);\nconst JOB_LIMIT = onum(\n \"Results per response, 1-100 (default 10, to keep page content inside the context window); page on with next_cursor.\"\n);\nconst JOB_INCLUDE_CONTENT = obool(\"Set false to list results without their page content (default true).\");\nconst JOB_STATUS_PARAMS = z.object({\n id: str(\"Job id returned when the job was started (data.id).\"),\n cursor: ostr(\"next_cursor from the previous response, to read the next page.\"),\n limit: JOB_LIMIT,\n status: ostr(\"Only results with this status: 'succeeded', 'failed' or 'skipped'.\"),\n include_content: JOB_INCLUDE_CONTENT,\n});\n\n/**\n * Build a Composio custom toolkit exposing Scavio search tools.\n *\n * Scavio is a single Search API over Google, YouTube, Amazon, Walmart, Reddit,\n * TikTok, TikTok Shop, Instagram, X and LinkedIn; this toolkit covers all ten.\n * Pass to `composio.create(userId, { experimental:\n * { customToolkits: [toolkit] } })`. Agent-facing slugs are prefixed `LOCAL_SCAVIO_`.\n */\nexport function buildScavioToolkit(options: BuildScavioToolkitOptions = {}) {\n const {\n apiKey,\n enableGoogle = true,\n enableAmazon = true,\n enableWalmart = true,\n enableYoutube = true,\n enableReddit = true,\n enableTiktok = true,\n enableTiktokShop = true,\n enableInstagram = true,\n enableX = true,\n enableLinkedin = true,\n enableExtract = true,\n enableThreads = false,\n enableKuaishou = false,\n enableEbay = false,\n enableTarget = false,\n enableHomeDepot = false,\n enableZillow = false,\n enableBooking = false,\n enableTripadvisor = false,\n enableIndeed = false,\n enableAirbnb = false,\n enableGlassdoor = false,\n enableYelp = false,\n enableAppStore = false,\n enableGooglePlay = false,\n enableSec = false,\n enableRedfin = false,\n enableCompaniesHouse = false,\n enableG2 = false,\n enableCapterra = false,\n enableGoogleAds = false,\n enableMetaAds = false,\n enableCrawl = false,\n pollIntervalMs = JOB_POLL_INTERVAL_MS,\n all = false,\n } = options;\n\n const client = new Scavio({ apiKey: apiKey ?? process.env.SCAVIO_API_KEY });\n\n function tool<T extends z.ZodTypeAny>(\n slug: string,\n name: string,\n description: string,\n inputParams: T,\n call: (input: z.infer<T>) => Promise<Record<string, unknown>>\n ) {\n return experimental_createTool(slug, {\n name,\n description,\n inputParams,\n execute: async (input: z.infer<T>) => call(input),\n });\n }\n\n const tools = [];\n\n // Google runs on /api/v2/google. Responses are FLAT - the provider payload is\n // spread at the top level next to response_time and credits_used, with no\n // `data` wrapper. All 14 endpoints cost 1 credit.\n if (all || enableGoogle) {\n tools.push(\n tool(\n \"GOOGLE_SEARCH\",\n \"Scavio Google Search\",\n \"Search Google for real-time web results. Returns organic_results (each with title, link and snippet) plus knowledge_graph, related_questions, ads and the AI Overview when Google shows one. The body is flat - read organic_results at the top level, not under data. Costs 1 credit.\",\n z.object({\n query: str(\"The search query (1-500 characters).\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n start: onum(\"Result offset, NOT a page number: 0 is page 1, 10 is page 2, up to 990.\"),\n time_period: ostr(\"Restrict results to a recent time window: 'last_hour', 'last_day', 'last_week', 'last_month', or 'last_year'.\"),\n safe: ostr(\"Turn SafeSearch on with 'active'.\"),\n nfpr: obool(\"Disable spelling correction and auto-fixes when true.\"),\n }),\n (i) => client.google.search(i as SdkOpts<typeof client.google.search>)\n ),\n tool(\n \"GOOGLE_AI_MODE\",\n \"Scavio Google AI Mode\",\n \"Ask Google AI Mode a question. Returns Google's generated answer with its cited sources - use this for a synthesized answer and GOOGLE_SEARCH for a ranked result list. Costs 1 credit.\",\n z.object({\n query: str(\"Question or prompt (1-500 characters).\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n safe: ostr(\"Turn SafeSearch on with 'active'.\"),\n }),\n (i) => client.google.aiMode(i as SdkOpts<typeof client.google.aiMode>)\n ),\n tool(\n \"GOOGLE_MAPS_SEARCH\",\n \"Scavio Google Maps Search\",\n \"Search Google Maps for local businesses and places. Returns local results with ratings, review counts, addresses, phone numbers and place ids. Feed a place_id into GOOGLE_MAPS_PLACE or GOOGLE_MAPS_REVIEWS. Costs 1 credit.\",\n z.object({\n query: str(\"Search query, e.g. 'coffee shops in Austin' (1-500 characters).\"),\n ll: ostr(\"Map centre as '@lat,lng,zoomz'; controls which area results come from. Maps localizes by map centre, not gl.\"),\n start: onum(\"Result offset; must be a multiple of 20 (0, 20, 40, ...).\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.mapsSearch(i)\n ),\n tool(\n \"GOOGLE_MAPS_PLACE\",\n \"Scavio Google Maps Place\",\n \"Fetch one Google Maps place in full: hours, address, phone, website, rating, price level and photos. Provide place_id or data_cid. Costs 1 credit.\",\n z.object({\n place_id: ostr(\"Place ID (starts with ChIJ). Provide this or data_cid.\"),\n data_cid: ostr(\"Numeric CID. Provide this or place_id.\"),\n }),\n (i) => client.google.mapsPlace(i)\n ),\n tool(\n \"GOOGLE_MAPS_REVIEWS\",\n \"Scavio Google Maps Reviews\",\n \"List Google Maps reviews for a place. Provide data_id or place_id. Page with next_page_token; each page costs another credit. Costs 1 credit.\",\n z.object({\n place_id: ostr(\"Place ID (starts with ChIJ). Provide this or data_id.\"),\n data_id: ostr(\"Data ID in 0xHEX:0xHEX form. Provide this or place_id.\"),\n num: onum(\"Reviews per page (1-20).\"),\n sort_by: ostr(\"Review sort order: 'relevance', 'newest', 'highest_rating', or 'lowest_rating'.\"),\n next_page_token: ostr(\"Pagination cursor from a prior response.\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.mapsReviews(i as SdkOpts<typeof client.google.mapsReviews>)\n ),\n tool(\n \"GOOGLE_SHOPPING\",\n \"Scavio Google Shopping\",\n \"Search Google Shopping. Returns product cards with prices, merchants, ratings and catalog ids across retailers - use this for cross-retailer price comparison and AMAZON_SEARCH or WALMART_SEARCH for a single marketplace. Costs 1 credit.\",\n z.object({\n query: str(\"Product search query (1-500 characters).\"),\n min_price: onum(\"Minimum price filter.\"),\n max_price: onum(\"Maximum price filter.\"),\n sort_by: onum(\"0 = relevance, 1 = price ascending, 2 = price descending.\"),\n free_shipping: obool(\"Only items with free shipping.\"),\n on_sale: obool(\"Only items on sale.\"),\n start: onum(\"Result offset.\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device,\n }),\n (i) => client.google.shopping(i as SdkOpts<typeof client.google.shopping>)\n ),\n tool(\n \"GOOGLE_SHOPPING_PRODUCT\",\n \"Scavio Google Shopping Product\",\n \"Fetch one Google Shopping product: specs, reviews, and the sellers carrying it. Pass catalog_id together with query for full detail and the seller list. Costs 1 credit.\",\n z.object({\n catalog_id: ostr(\"Durable product catalog id from a shopping search.\"),\n query: ostr(\"Product query. Required when catalog_id is set.\"),\n product_id: ostr(\"Product id, as an alternative to catalog_id.\"),\n page_token: ostr(\"Immersive product page token.\"),\n sort_by: ostr(\"Seller sort order: 'base_price', 'total_price', 'promotion', or 'seller_rating'.\"),\n load_all_stores: obool(\"Load every available store.\"),\n more_stores: obool(\"Fetch additional stores.\"),\n gl,\n hl,\n google_domain: googleDomain,\n location,\n device: ostr(\"Device to emulate: 'desktop', 'mobile', or 'tablet'.\"),\n }),\n (i) => client.google.shoppingProduct(i as SdkOpts<typeof client.google.shoppingProduct>)\n ),\n tool(\n \"GOOGLE_SHOPPING_STORES\",\n \"Scavio Google Shopping Stores\",\n \"Fetch the next page of sellers for a Google Shopping product. Continuation of GOOGLE_SHOPPING_PRODUCT: pass the same catalog_id plus that response's next_page_token. Costs 1 credit.\",\n z.object({\n catalog_id: str(\"Durable product catalog id.\"),\n next_page_token: str(\"Pagination cursor from GOOGLE_SHOPPING_PRODUCT.\"),\n }),\n (i) => client.google.shoppingStores(i)\n ),\n tool(\n \"GOOGLE_FLIGHTS\",\n \"Scavio Google Flights\",\n \"Search Google Flights. Returns itineraries with prices, airlines, stops, durations and carbon emissions. Airports are IATA codes; dates are YYYY-MM-DD. Costs 1 credit.\",\n z.object({\n departure_id: str(\"Departure IATA code(s), comma-separated allowed, e.g. 'JFK'.\"),\n arrival_id: str(\"Arrival IATA code(s), comma-separated allowed, e.g. 'LHR'.\"),\n outbound_date: str(\"Outbound date (YYYY-MM-DD).\"),\n return_date: ostr(\"Return date (YYYY-MM-DD). Required when type is 1.\"),\n type: onum(\"1 = round trip (default), 2 = one way, 3 = multi-city.\"),\n adults: onum(\"Number of adults (1-9).\"),\n children: onum(\"Number of children (0-9).\"),\n infants_in_seat: onum(\"Infants in seat (0-4).\"),\n infants_on_lap: onum(\"Infants on lap (0-4).\"),\n travel_class: onum(\"1 = economy, 2 = premium economy, 3 = business, 4 = first.\"),\n stops: onum(\"0 = any, 1 = nonstop, 2 = one stop or fewer, 3 = two or fewer.\"),\n sort_by: onum(\"1 = top, 2 = price, 3 = departure, 4 = arrival, 5 = duration, 6 = emissions.\"),\n include_airlines: ostr(\"Comma-separated airline or alliance codes to include.\"),\n exclude_airlines: ostr(\"Comma-separated airline or alliance codes to exclude.\"),\n currency,\n gl,\n hl,\n }),\n (i) => client.google.flights(i)\n ),\n tool(\n \"GOOGLE_HOTELS\",\n \"Scavio Google Hotels\",\n \"Search Google Hotels. Returns properties with nightly prices, ratings, amenities and a detail_token for GOOGLE_HOTELS_DETAIL. Phrase the query as '<City> hotels'. Costs 1 credit.\",\n z.object({\n query: str(\"Search query; use a '<City> hotels' form.\"),\n check_in_date: checkInDate,\n check_out_date: checkOutDate,\n sort_by: onum(\"3 = lowest price, 8 = highest rating, 13 = most reviewed.\"),\n min_price: onum(\"Minimum nightly price.\"),\n max_price: onum(\"Maximum nightly price.\"),\n rating: onum(\"7 = 3.5+, 8 = 4.0+, 9 = 4.5+.\"),\n hotel_class: ostr(\"Comma-separated star ratings (2-5).\"),\n amenities: ostr(\"Comma-separated amenity ids.\"),\n property_types: ostr(\"Comma-separated property-type ids, e.g. '12' for vacation rentals.\"),\n free_cancellation: obool(\"Only properties with free cancellation.\"),\n eco_certified: obool(\"Only eco-certified properties.\"),\n special_offers: obool(\"Only properties with special offers.\"),\n limit: onum(\"Number of properties to return (1-20).\"),\n next_page_token: ostr(\"Pagination cursor from a prior response.\"),\n currency,\n gl,\n hl,\n }),\n (i) => client.google.hotels(i)\n ),\n tool(\n \"GOOGLE_HOTELS_DETAIL\",\n \"Scavio Google Hotels Detail\",\n \"Fetch one Google Hotels property in full: room types, per-night prices by provider, amenities, photos and reviews. Needs a detail_token from GOOGLE_HOTELS and the same stay dates. Costs 1 credit.\",\n z.object({\n detail_token: str(\"Property detail token from a hotels listing.\"),\n check_in_date: checkInDate,\n check_out_date: checkOutDate,\n currency,\n gl,\n hl,\n }),\n (i) => client.google.hotelsDetail(i)\n ),\n tool(\n \"GOOGLE_NEWS\",\n \"Scavio Google News\",\n \"Fetch Google News. Pass query to search, or a topic_token / story_token / publication_token from an earlier response to browse a topic, a full story or one publisher. Costs 1 credit.\",\n z.object({\n query: ostr(\"Keyword search.\"),\n topic_token: ostr(\"Browse a news topic.\"),\n section_token: ostr(\"Browse a topic section.\"),\n story_token: ostr(\"Fetch full coverage of one story.\"),\n publication_token: ostr(\"Browse one publication.\"),\n kgmid: ostr(\"Knowledge Graph entity id.\"),\n so: onum(\"Sort: 0 = relevance, 1 = date. Only applies with query or kgmid.\"),\n gl,\n hl,\n google_domain: googleDomain,\n }),\n (i) => client.google.news(i)\n ),\n tool(\n \"GOOGLE_TRENDS\",\n \"Scavio Google Trends\",\n \"Fetch Google Trends interest data. Comma-separate the query to compare terms, and pick the dataset with data_type: TIMESERIES for interest over time, GEO_MAP for interest by region, RELATED_QUERIES or RELATED_TOPICS for rising searches. Costs 1 credit.\",\n z.object({\n query: str(\"Search term(s); comma-separated to compare up to five.\"),\n data_type: ostr(\"Which trends dataset to return: 'TIMESERIES', 'GEO_MAP', 'GEO_MAP_0', 'RELATED_QUERIES', or 'RELATED_TOPICS'.\"),\n geo: ostr(\"Location code, e.g. 'US', 'GB', 'US-CA'. Omit for worldwide.\"),\n date: ostr(\"Time range, e.g. 'today 12-m', 'now 7-d'.\"),\n cat: ostr(\"Category id.\"),\n gprop: ostr(\"Restrict to a Google property: 'images', 'news', 'youtube', or 'froogle'.\"),\n region: ostr(\"Resolution for GEO_MAP data: 'COUNTRY', 'REGION', 'DMA', or 'CITY'.\"),\n tz: ostr(\"Timezone offset in minutes.\"),\n hl,\n }),\n (i) => client.google.trends(i as SdkOpts<typeof client.google.trends>)\n ),\n tool(\n \"GOOGLE_TRENDING\",\n \"Scavio Google Trending\",\n \"List what is trending on Google right now for one country. geo is required. Use GOOGLE_TRENDS instead when you already know the term you care about. Costs 1 credit.\",\n z.object({\n geo: str(\"Country code, e.g. 'US'.\"),\n hours: onum(\"Trending window in hours: 4, 24, 48 or 168.\"),\n cat: onum(\"Category id (0-20).\"),\n sort: ostr(\"Sort order: 'relevance', 'search_volume', 'recency', or 'title'.\"),\n status: ostr(\"Filter by trend status: 'all' or 'active'.\"),\n hl,\n }),\n (i) => client.google.trending(i as SdkOpts<typeof client.google.trending>)\n )\n );\n }\n\n // Amazon moved upstream in 2026-07: sort_by, pages, category_id, merchant_id,\n // language, currency, device, zip_code and autoselect_variant no longer exist.\n // Removed rather than kept as no-ops - sort_by was verified to return the\n // identical unordered set for every value. `domain` still works on the wire\n // as a deprecated alias but is not offered: one spelling per param.\n if (all || enableAmazon) {\n tools.push(\n tool(\n \"AMAZON_SEARCH\",\n \"Scavio Amazon Search\",\n \"Search Amazon for products matching a query. Results are unsorted and cannot be filtered by category, merchant or price. Costs 1 credit.\",\n z.object({\n query: str(\"The product search query.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n page: onum(\"Result page, 1-based. One page per call, 1 credit each.\"),\n }),\n (i) => client.amazon.search(i as SdkOpts<typeof client.amazon.search>)\n ),\n tool(\n \"AMAZON_PRODUCT\",\n \"Scavio Amazon Product\",\n \"Fetch full Amazon product details by ASIN. price is the buy-box price only. Costs 1 credit.\",\n z.object({\n asin: str(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n }),\n (i) => client.amazon.product(i as SdkOpts<typeof client.amazon.product>)\n ),\n tool(\n \"AMAZON_OFFERS\",\n \"Scavio Amazon Offers\",\n \"List every seller offer for one Amazon ASIN: price, seller, condition, shipping, and which offer holds the buy box. Page 1 only. Use this instead of AMAZON_PRODUCT when comparing sellers or checking who owns the buy box. Costs 1 credit.\",\n z.object({\n asin: str(\"Amazon Standard Identification Number (ASIN) of the product.\"),\n country: ostr(\"Marketplace country code (ISO 3166-1 alpha-2), not a domain: 'us' (default), 'gb' (the UK is gb, not uk), 'ca', 'de', 'fr', 'es', 'it', 'jp', 'in', 'au', 'br', 'mx', 'nl', 'pl', 'se', 'sg', 'ae', 'sa', 'eg', 'cn', 'be', 'tr'. An unknown code falls back to us.\"),\n }),\n (i) => client.amazon.offers(i as SdkOpts<typeof client.amazon.offers>)\n ),\n tool(\n \"AMAZON_OPTIONS\",\n \"Scavio Amazon Options\",\n \"Supported Amazon marketplaces, as 'domains' and 'countries'. 'languages' and 'currencies' remain in the payload but are always empty: neither is a request param any more. Needs no API key and costs no credits.\",\n z.object({}),\n () => client.amazon.options()\n )\n );\n }\n\n // Walmart was rebuilt: device, delivery_zip and store_id\n // never existed on it, start_page is now page, and it is BODY-PRICED - 1 credit\n // on domain com/ca, 2 on com.mx, so search and category alone carry a domain.\n if (all || enableWalmart) {\n tools.push(\n tool(\n \"WALMART_SEARCH\",\n \"Scavio Walmart Search\",\n \"Search Walmart and get structured product rows (products, products_count and the store the results were priced against). Costs 1 credit on domain 'com' or 'ca' and 2 credits on 'com.mx' - the price is a function of the request body, not a constant for the route.\",\n z.object({\n query: str(\"Product search query (1-500 characters).\"),\n domain: ostr(\"Marketplace: 'com' (US, default, 1 credit), 'ca' (1 credit), 'com.mx' (2 credits). Sets the currency and product URLs of the response.\"),\n page: onum(\"Results page, 1-based (integer >= 1). One page per call.\"),\n start_page: onum(\"Deprecated alias for page; send page instead.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Accepted values: 'best_match', 'price_low', 'price_high', 'best_seller', 'rating_high', 'new'.\"),\n min_price: onum(\"Minimum price filter in the marketplace's own currency; decimals allowed (e.g. 19.99).\"),\n max_price: onum(\"Maximum price filter in the marketplace's own currency; decimals allowed (e.g. 199.5).\"),\n fulfillment_speed: ostr(\"Only items deliverable today, or by tomorrow. '2_days' and 'anytime' are not accepted - for anytime, omit this parameter.\"),\n fulfillment_type: ostr(\"Set to 'in_store' to return only items available for in-store pickup.\"),\n }),\n (i) => client.walmart.search(i as SdkOpts<typeof client.walmart.search>)\n ),\n tool(\n \"WALMART_PRODUCT\",\n \"Scavio Walmart Product\",\n \"Full detail for a single Walmart product: price, rating, images, specifications, availability and seller. US marketplace only - walmart.ca product pages could not be fetched at all, so this endpoint takes no domain. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '13544111159'.\"),\n }),\n (i) => client.walmart.product(i as SdkOpts<typeof client.walmart.product>)\n ),\n tool(\n \"WALMART_REVIEWS\",\n \"Scavio Walmart Reviews\",\n \"Customer reviews for a Walmart product with ratings, text, author, date and the rating breakdown. 10 reviews per page; paginate with page. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '13544111159'.\"),\n page: onum(\"Reviews page, 1-based (integer >= 1). 10 reviews per page.\"),\n sort: ostr(\"Review sort order. Omit for Walmart's own default ordering. Accepted values: 'relevancy', 'submission-desc', 'submission-asc', 'rating-desc', 'rating-asc', 'helpful-desc'.\"),\n }),\n (i) => client.walmart.reviews(i as SdkOpts<typeof client.walmart.reviews>)\n ),\n tool(\n \"WALMART_CATEGORY\",\n \"Scavio Walmart Category\",\n \"Products within a Walmart category, in the same product shape as search. Costs 1 credit on domain 'com' or 'ca' and 2 credits on 'com.mx' - the price is a function of the request body, not a constant for the route.\",\n z.object({\n category_id: str(\"Walmart category id: either a leaf id ('1095191') or the full underscore-joined path ('3944_133251_1095191'). Both are accepted.\"),\n domain: ostr(\"Marketplace: 'com' (US, default, 1 credit), 'ca' (1 credit), 'com.mx' (2 credits). Sets the currency and product URLs of the response.\"),\n page: onum(\"Results page, 1-based (integer >= 1). One page per call.\"),\n limit: onum(\"Trim the returned products to at most this many (integer >= 1). Applied after fetching, so it does not reduce the credit cost of the call.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Accepted values: 'best_match', 'price_low', 'price_high', 'best_seller', 'rating_high', 'new'.\"),\n min_price: onum(\"Minimum price filter in the marketplace's own currency; decimals allowed (e.g. 19.99).\"),\n max_price: onum(\"Maximum price filter in the marketplace's own currency; decimals allowed (e.g. 199.5).\"),\n fulfillment_speed: ostr(\"Only items deliverable today, or by tomorrow. '2_days' and 'anytime' are not accepted - for anytime, omit this parameter.\"),\n }),\n (i) => client.walmart.category(i as SdkOpts<typeof client.walmart.category>)\n ),\n tool(\n \"WALMART_OFFERS\",\n \"Scavio Walmart Offers\",\n \"The buy-box offer for a Walmart product: price, seller, condition and buy-box flag. BUY-BOX SELLER ONLY - this is not the full offer list, and there is no way to page through the other sellers. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n product_id: str(\"Walmart item id (usItemId), e.g. '2979510112'.\"),\n }),\n (i) => client.walmart.offers(i as SdkOpts<typeof client.walmart.offers>)\n ),\n tool(\n \"WALMART_SELLER\",\n \"Scavio Walmart Seller\",\n \"Marketplace seller storefront: name, rating, review count, Pro Seller badge and business details. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n seller_id: str(\"Numeric Walmart catalog seller id, as returned in `seller_catalog_id` on a product, search or offers response (e.g. '101480084'). The GUID `seller_id` is not accepted here - it 404s.\"),\n }),\n (i) => client.walmart.seller(i as SdkOpts<typeof client.walmart.seller>)\n ),\n tool(\n \"WALMART_SELLER_PRODUCTS\",\n \"Scavio Walmart Seller Products\",\n \"A marketplace seller's catalog. Roughly the first 40 items are server-rendered and returned; total_count reports the seller's real catalog size. There is no pagination - the rest of the catalog is not reachable. Costs 1 credit: Walmart is body-priced through `domain`, but this endpoint takes no domain, so it is always 1.\",\n z.object({\n seller_id: str(\"Numeric Walmart catalog seller id, as returned in `seller_catalog_id` on a product, search or offers response (e.g. '101480084'). The GUID `seller_id` 404s.\"),\n }),\n (i) => client.walmart.sellerProducts(i as SdkOpts<typeof client.walmart.sellerProducts>)\n )\n );\n }\n\n // /youtube/metadata is a deprecated alias of /youtube/video and is deliberately\n // not exposed - two tools for one endpoint only makes an agent pick wrong.\n if (all || enableYoutube) {\n tools.push(\n tool(\n \"YOUTUBE_SEARCH\",\n \"Scavio YouTube Search\",\n \"Search YouTube for videos, channels, or playlists. Costs 2 credits.\",\n z.object({\n query: str(\"The video search query.\"),\n upload_date: ostr(\"Upload date filter: 'last_hour', 'today', 'this_week', 'this_month', 'this_year'.\"),\n type: ostr(\"Result type: 'video', 'channel', 'playlist', or 'movie'.\"),\n duration: ostr(\"Duration filter: 'short', 'medium', or 'long'.\"),\n sort_by: ostr(\"Sort order: 'relevance', 'date', 'view_count', or 'rating'.\"),\n features: z.array(z.string()).optional().describe(\"Feature filters, e.g. ['hd', '4k', 'subtitles', 'creative_commons', 'live', '360', '3d', 'hdr', 'vr180'].\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n hd: obool(\"Restrict to HD videos when true.\"),\n subtitles: obool(\"Restrict to videos with subtitles when true.\"),\n creative_commons: obool(\"Restrict to Creative Commons videos when true.\"),\n live: obool(\"Restrict to live videos when true.\"),\n }),\n (i) => client.youtube.search(i as SdkOpts<typeof client.youtube.search>)\n ),\n tool(\n \"YOUTUBE_SHORTS\",\n \"Scavio YouTube Shorts\",\n \"Search YouTube Shorts. Costs 2 credits.\",\n z.object({\n query: str(\"The Shorts search query.\"),\n sort_by: ostr(\"Sort order: 'relevance', 'date', 'view_count', or 'rating'.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.shorts(i as SdkOpts<typeof client.youtube.shorts>)\n ),\n tool(\n \"YOUTUBE_SUGGESTIONS\",\n \"Scavio YouTube Suggestions\",\n \"Get YouTube search autocomplete suggestions for a partial query. Costs 1 credit.\",\n z.object({\n query: str(\"The partial query to autocomplete.\"),\n language: ostr(\"Suggestion language (ISO 639-1, default 'en').\"),\n region: ostr(\"Region code (ISO 3166-1 alpha-2, default 'US').\"),\n }),\n (i) => client.youtube.suggestions(i)\n ),\n tool(\n \"YOUTUBE_VIDEO\",\n \"Scavio YouTube Video\",\n \"Fetch full metadata for a YouTube video by id or watch URL. Costs 1 credit.\",\n z.object({ video_id: str(\"YouTube video id or a full watch URL.\") }),\n (i) => client.youtube.video(i)\n ),\n tool(\n \"YOUTUBE_COMMENTS\",\n \"Scavio YouTube Comments\",\n \"List top-level comments on a YouTube video. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.comments(i)\n ),\n tool(\n \"YOUTUBE_COMMENT_REPLIES\",\n \"Scavio YouTube Comment Replies\",\n \"List replies to a YouTube comment using its reply cursor. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n reply_cursor: str(\"Reply cursor from a parent comment's 'reply_cursor' field.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.commentReplies(i)\n ),\n tool(\n \"YOUTUBE_TRANSCRIPT\",\n \"Scavio YouTube Transcript\",\n \"Fetch the transcript or timed captions for a YouTube video. Costs 5 credits.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n language: ostr(\"Caption language code (default 'en').\"),\n format: ostr(\"'text' for a plain transcript or 'srt' for timed subtitles (default 'text').\"),\n }),\n (i) => client.youtube.transcript(i as SdkOpts<typeof client.youtube.transcript>)\n ),\n tool(\n \"YOUTUBE_RELATED\",\n \"Scavio YouTube Related\",\n \"List videos related to a YouTube video. Costs 1 credit.\",\n z.object({\n video_id: str(\"YouTube video id or a full watch URL.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.related(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_SEARCH\",\n \"Scavio YouTube Channel Search\",\n \"Search YouTube channels by keyword. Costs 1 credit.\",\n z.object({\n query: str(\"The channel search query.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelSearch(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL\",\n \"Scavio YouTube Channel\",\n \"Fetch YouTube channel details by id, @handle, or URL. Costs 1 credit.\",\n z.object({ channel_id: str(\"YouTube channel id, @handle, or channel URL.\") }),\n (i) => client.youtube.channel(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_VIDEOS\",\n \"Scavio YouTube Channel Videos\",\n \"List videos uploaded by a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelVideos(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_SHORTS\",\n \"Scavio YouTube Channel Shorts\",\n \"List Shorts posted by a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelShorts(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_COMMUNITY\",\n \"Scavio YouTube Channel Community\",\n \"List community posts from a YouTube channel. Costs 1 credit.\",\n z.object({\n channel_id: str(\"YouTube channel id.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.youtube.channelCommunity(i)\n ),\n tool(\n \"YOUTUBE_CHANNEL_RESOLVE\",\n \"Scavio YouTube Channel Resolve\",\n \"Resolve a YouTube @handle or channel URL to a channel id. Costs 1 credit.\",\n z.object({ channel: str(\"A channel @handle or channel URL to resolve to a channel id.\") }),\n (i) => client.youtube.channelResolve(i)\n ),\n tool(\n \"YOUTUBE_STREAMS\",\n \"Scavio YouTube Streams\",\n \"Fetch playable or downloadable stream formats for a YouTube video. Costs 3 credits.\",\n z.object({ video_id: str(\"YouTube video id or a full watch URL.\") }),\n (i) => client.youtube.streams(i)\n )\n );\n }\n\n // /reddit/search takes ONLY query + cursor. `type` and `sort` were never real:\n // the API strips unknown fields, so they filtered nothing while making the agent\n // believe the result set was narrowed. Removed rather than kept as no-ops.\n // Sort defaults differ per endpoint (TOP for comments, HOT for a subreddit feed,\n // NEW for a user feed) and values are UPPERCASE; only the subreddit feed accepts\n // RISING. All twelve endpoints cost 1 credit.\n if (all || enableReddit) {\n tools.push(\n tool(\n \"REDDIT_SEARCH\",\n \"Scavio Reddit Search\",\n \"Search Reddit posts. Returns data.results with next_cursor and has_more; page with cursor. Results cannot be filtered or sorted. Costs 1 credit.\",\n z.object({\n query: str(\"The Reddit search query.\"),\n cursor: ostr(\"Pagination cursor: pass 'next_cursor' from a prior response.\"),\n }),\n (i) => client.reddit.search(i as SdkOpts<typeof client.reddit.search>)\n ),\n tool(\n \"REDDIT_SEARCH_SUGGESTIONS\",\n \"Scavio Reddit Search Suggestions\",\n \"Get Reddit search autocomplete suggestions for a query. Returns data.suggestions (plain strings) and total_count. Costs 1 credit.\",\n z.object({ query: str(\"The partial or full query to expand.\") }),\n (i) => client.reddit.searchSuggestions(i)\n ),\n tool(\n \"REDDIT_POST\",\n \"Scavio Reddit Post\",\n \"Fetch one Reddit post by URL or post id. Returns a FLAT post object under data (post_id, title, text, url, subreddit, author, score, upvote_ratio, num_comments, created_at, is_nsfw, is_video, thumbnail, media); comments are NOT included - call REDDIT_POST_COMMENTS for those. Costs 1 credit.\",\n z.object({\n url: ostr(\"Full URL of the Reddit post. Provide this or post_id.\"),\n post_id: ostr(\"Post fullname (t3_...) or bare id. Provide this or url.\"),\n }),\n (i) => client.reddit.post(i)\n ),\n tool(\n \"REDDIT_POST_COMMENTS\",\n \"Scavio Reddit Post Comments\",\n \"List top-level comments on a Reddit post. Returns data.comments with next_cursor and has_more; each comment carries a reply_cursor for REDDIT_COMMENT_REPLIES. Costs 1 credit.\",\n z.object({\n post_id: str(\"Post fullname (t3_...), bare id, or post URL.\"),\n sort: ostr(\"Comment sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to TOP.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.postComments(i as SdkOpts<typeof client.reddit.postComments>)\n ),\n tool(\n \"REDDIT_COMMENT_REPLIES\",\n \"Scavio Reddit Comment Replies\",\n \"List replies to one Reddit comment. cursor is REQUIRED here and must be a comment's 'reply_cursor' from REDDIT_POST_COMMENTS, not a 'next_cursor'. Costs 1 credit.\",\n z.object({\n post_id: str(\"Post fullname (t3_...) the comment belongs to.\"),\n cursor: str(\"A comment's 'reply_cursor' from REDDIT_POST_COMMENTS. Required.\"),\n sort: ostr(\"Comment sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to TOP.\"),\n }),\n (i) => client.reddit.commentReplies(i as SdkOpts<typeof client.reddit.commentReplies>)\n ),\n tool(\n \"REDDIT_SUBREDDIT\",\n \"Scavio Reddit Subreddit\",\n \"Fetch a subreddit's profile: title, description, subscribers, active_count, type, icon, banner and created_at. Costs 1 credit.\",\n z.object({ subreddit: str(\"Subreddit name without the r/ prefix, e.g. 'AskReddit'.\") }),\n (i) => client.reddit.subreddit(i)\n ),\n tool(\n \"REDDIT_SUBREDDIT_POSTS\",\n \"Scavio Reddit Subreddit Posts\",\n \"List posts in a subreddit feed. Returns data.posts with next_cursor and has_more. This feed shape has no text and no thumbnail - use REDDIT_POST for a post's body. Costs 1 credit.\",\n z.object({\n subreddit: str(\"Subreddit name without the r/ prefix.\"),\n sort: ostr(\"Feed sort order (UPPERCASE): 'BEST', 'HOT', 'NEW', 'TOP', 'CONTROVERSIAL', or 'RISING'. Defaults to HOT. This is the only endpoint accepting RISING.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.subredditPosts(i as SdkOpts<typeof client.reddit.subredditPosts>)\n ),\n tool(\n \"REDDIT_USER\",\n \"Scavio Reddit User\",\n \"Fetch a redditor's profile: karma split, account_type, avatar, description, verification flags and created_at. Costs 1 credit.\",\n z.object({ username: str(\"Redditor username without the u/ prefix, e.g. 'spez'.\") }),\n (i) => client.reddit.user(i)\n ),\n tool(\n \"REDDIT_USER_POSTS\",\n \"Scavio Reddit User Posts\",\n \"List posts submitted by a redditor. Returns data.posts with next_cursor and has_more. Costs 1 credit.\",\n z.object({\n username: str(\"Redditor username without the u/ prefix.\"),\n sort: ostr(\"Sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to NEW.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.userPosts(i as SdkOpts<typeof client.reddit.userPosts>)\n ),\n tool(\n \"REDDIT_USER_COMMENTS\",\n \"Scavio Reddit User Comments\",\n \"List comments written by a redditor. Returns data.comments with next_cursor and has_more; each item nests the post it belongs to. Costs 1 credit.\",\n z.object({\n username: str(\"Redditor username without the u/ prefix.\"),\n sort: ostr(\"Sort order (UPPERCASE): 'HOT', 'NEW', 'TOP', 'BEST', or 'CONTROVERSIAL'. Defaults to NEW.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.reddit.userComments(i as SdkOpts<typeof client.reddit.userComments>)\n ),\n tool(\n \"REDDIT_POPULAR\",\n \"Scavio Reddit Popular\",\n \"List the site-wide r/popular feed. Returns data.posts with next_cursor and has_more. Costs 1 credit.\",\n z.object({ cursor: ostr(\"Pagination cursor from a prior response. Omit for page 1.\") }),\n (i) => client.reddit.popular(i)\n ),\n tool(\n \"REDDIT_TRENDING\",\n \"Scavio Reddit Trending\",\n \"List Reddit's currently trending searches. Returns data.trending (query plus raw_query) and total_count. Takes no parameters. Costs 1 credit.\",\n z.object({}),\n () => client.reddit.trending()\n )\n );\n }\n\n if (all || enableTiktok) {\n tools.push(\n tool(\n \"TIKTOK_PROFILE\",\n \"Scavio TikTok Profile\",\n \"Fetch a TikTok user profile by username or secUid. Costs 1 credit.\",\n z.object({\n username: ostr(\"TikTok username (without @). Provide this or sec_user_id.\"),\n sec_user_id: ostr(\"TikTok secUid. Provide this or username.\"),\n }),\n (i) => client.tiktok.profile(i)\n ),\n tool(\n \"TIKTOK_USER_POSTS\",\n \"Scavio TikTok User Posts\",\n \"List a TikTok user's posts by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of posts to return.\"),\n sort_type: ostr(\"Sort order for posts.\"),\n }),\n (i) => client.tiktok.userPosts(i as SdkOpts<typeof client.tiktok.userPosts>)\n ),\n tool(\n \"TIKTOK_VIDEO\",\n \"Scavio TikTok Video\",\n \"Fetch a TikTok video by id. Costs 1 credit.\",\n z.object({ video_id: str(\"TikTok video id.\") }),\n (i) => client.tiktok.video(i)\n ),\n tool(\n \"TIKTOK_VIDEO_COMMENTS\",\n \"Scavio TikTok Video Comments\",\n \"List comments on a TikTok video. Costs 1 credit.\",\n z.object({\n video_id: str(\"TikTok video id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of comments to return.\"),\n }),\n (i) => client.tiktok.videoComments(i)\n ),\n tool(\n \"TIKTOK_COMMENT_REPLIES\",\n \"Scavio TikTok Comment Replies\",\n \"List replies to a TikTok video comment. Costs 1 credit.\",\n z.object({\n video_id: str(\"TikTok video id.\"),\n comment_id: str(\"Parent comment id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of replies to return.\"),\n }),\n (i) => client.tiktok.commentReplies(i)\n ),\n tool(\n \"TIKTOK_SEARCH_VIDEOS\",\n \"Scavio TikTok Search Videos\",\n \"Search TikTok videos by keyword. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of videos to return.\"),\n sort_type: ostr(\"Sort order for results.\"),\n publish_time: ostr(\"Publish-time filter.\"),\n }),\n (i) => client.tiktok.searchVideos(i as SdkOpts<typeof client.tiktok.searchVideos>)\n ),\n tool(\n \"TIKTOK_SEARCH_USERS\",\n \"Scavio TikTok Search Users\",\n \"Search TikTok users by keyword. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of users to return.\"),\n }),\n (i) => client.tiktok.searchUsers(i)\n ),\n tool(\n \"TIKTOK_HASHTAG\",\n \"Scavio TikTok Hashtag\",\n \"Fetch a TikTok hashtag by name or id. Costs 1 credit.\",\n z.object({\n hashtag_name: ostr(\"Hashtag name (without #). Provide this or hashtag_id.\"),\n hashtag_id: ostr(\"Hashtag id. Provide this or hashtag_name.\"),\n }),\n (i) => client.tiktok.hashtag(i)\n ),\n tool(\n \"TIKTOK_HASHTAG_VIDEOS\",\n \"Scavio TikTok Hashtag Videos\",\n \"List videos for a TikTok hashtag by id. Costs 1 credit.\",\n z.object({\n hashtag_id: str(\"Hashtag id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n count: onum(\"Number of videos to return.\"),\n }),\n (i) => client.tiktok.hashtagVideos(i)\n ),\n tool(\n \"TIKTOK_USER_FOLLOWERS\",\n \"Scavio TikTok User Followers\",\n \"List a TikTok user's followers by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n count: onum(\"Number of followers to return.\"),\n page_token: ostr(\"Pagination token.\"),\n min_time: onum(\"Minimum timestamp filter.\"),\n }),\n (i) => client.tiktok.userFollowers(i)\n ),\n tool(\n \"TIKTOK_USER_FOLLOWINGS\",\n \"Scavio TikTok User Followings\",\n \"List the accounts a TikTok user follows, by secUid. Costs 1 credit.\",\n z.object({\n sec_user_id: str(\"TikTok secUid of the user.\"),\n count: onum(\"Number of followings to return.\"),\n page_token: ostr(\"Pagination token.\"),\n min_time: onum(\"Minimum timestamp filter.\"),\n }),\n (i) => client.tiktok.userFollowings(i)\n )\n );\n }\n\n // TikTok Shop: 8 endpoints, 1 credit each. Two different region enums on\n // purpose - the listing endpoints serve US and GB only, everything else serves\n // the full eight, and /tiktok-shop/search takes no region at all (US catalog).\n // Cursors are opaque blobs from a prior next_cursor; a foreign cursor 400s.\n if (all || enableTiktokShop) {\n tools.push(\n tool(\n \"TIKTOK_SHOP_SEARCH\",\n \"Scavio TikTok Shop Search\",\n \"Search TikTok Shop products by keyword (US catalog only), up to 30 per page with exact prices, ratings and shop details. One of the three endpoints that return exact prices. Paginate with next_cursor and dedupe by product_id across pages. Costs 1 credit.\",\n z.object({\n search: str(\"Search query (1-200 characters). The keyword field is named 'search', not 'query'.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.tiktokShop.search(i)\n ),\n tool(\n \"TIKTOK_SHOP_SEARCH_SUGGESTIONS\",\n \"Scavio TikTok Shop Search Suggestions\",\n \"Expand a partial TikTok Shop query into keyword suggestions across 8 marketplace regions. Suggestions are not guaranteed prefix matches: a misspelling returns typo corrections, and results can include brand and shop names. Costs 1 credit.\",\n z.object({\n search: str(\"Partial query to expand (1-100 characters). The field is 'search', not 'query'.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.searchSuggestions(i as SdkOpts<typeof client.tiktokShop.searchSuggestions>)\n ),\n tool(\n \"TIKTOK_SHOP_PRODUCT\",\n \"Scavio TikTok Shop Product\",\n \"Full TikTok Shop product detail: description, images, variants with stock, shipping, shop profile, category path and top reviews. Two limits: it does NOT return a price (upstream masks it - get prices from TIKTOK_SHOP_SEARCH, TIKTOK_SHOP_SHOP_PRODUCTS or TIKTOK_SHOP_CATEGORY_PRODUCTS), and it resolves only about 44% of the product ids returned by search, so a 404 is a normal outcome to skip rather than retry. Costs 1 credit.\",\n z.object({\n product_id: str(\"TikTok Shop product id (6-25 digits).\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.product(i as SdkOpts<typeof client.tiktokShop.product>)\n ),\n tool(\n \"TIKTOK_SHOP_PRODUCT_REVIEWS\",\n \"Scavio TikTok Shop Product Reviews\",\n \"Paginated TikTok Shop product reviews with text, images, star histogram and verified-purchase flags, up to 200 per call. total_reviews drifts between calls and must NOT be used to compute a page count - page with has_more instead. Often works for ids TIKTOK_SHOP_PRODUCT cannot resolve. Costs 1 credit.\",\n z.object({\n product_id: str(\"TikTok Shop product id (6-25 digits).\"),\n page: onum(\"1-based page number (1-500, default 1).\"),\n page_size: onum(\"Reviews per page (1-200, default 20).\"),\n sort: ostr(\"'relevant' (default) is text-complete and image-heavy; 'recent' is fresher but far more text-sparse.\"),\n rating: onum(\"Only reviews with this star rating (1-5).\"),\n has_media: obool(\"Only reviews with a photo or video. Shares one upstream slot with verified_only, and wins when both are set.\"),\n verified_only: obool(\"Only verified purchases. Ignored when has_media is also set.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.productReviews(i as SdkOpts<typeof client.tiktokShop.productReviews>)\n ),\n tool(\n \"TIKTOK_SHOP_CATEGORIES\",\n \"Scavio TikTok Shop Categories\",\n \"The global TikTok Shop category tree: 28 top-level categories, 240 nodes, two levels deep. Category ids are identical in every region and names are always English. Takes no parameters. Costs 1 credit.\",\n z.object({}),\n () => client.tiktokShop.categories()\n ),\n tool(\n \"TIKTOK_SHOP_CATEGORY_PRODUCTS\",\n \"Scavio TikTok Shop Category Products\",\n \"Products listed under a category id from TIKTOK_SHOP_CATEGORIES, with exact prices. Level 1 or 2 ids both work. Page size is inconsistent upstream (15 to 20), so always paginate with next_cursor; when has_more turns false after a few pages that is the end of a shallow listing, not an error. Costs 1 credit.\",\n z.object({\n category_id: str(\"Category id from TIKTOK_SHOP_CATEGORIES; level 1 or 2 both work.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n region: ostr(\"Marketplace region, 'US' (default) or 'GB' only - not the 8-region list.\"),\n }),\n (i) => client.tiktokShop.categoryProducts(i as SdkOpts<typeof client.tiktokShop.categoryProducts>)\n ),\n tool(\n \"TIKTOK_SHOP_SHOP_PRODUCTS\",\n \"Scavio TikTok Shop Shop Products\",\n \"A shop's TikTok Shop catalog, 30 per page, with exact prices. Shop follower count, location and shop-level rating are not available here - call TIKTOK_SHOP_PRODUCT for the full shop profile. Costs 1 credit.\",\n z.object({\n shop_id: str(\"TikTok Shop seller id (also called seller_id elsewhere on TikTok).\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n region: ostr(\"Marketplace region: 'US' (default), 'GB', 'SG', 'MY', 'PH', 'TH', 'VN', or 'ID'.\"),\n }),\n (i) => client.tiktokShop.shopProducts(i as SdkOpts<typeof client.tiktokShop.shopProducts>)\n ),\n tool(\n \"TIKTOK_SHOP_RESOLVE\",\n \"Scavio TikTok Shop Resolve\",\n \"Resolve any TikTok Shop URL or share link to a product_id or shop_id, ready for the other TikTok Shop tools. Accepts shop.tiktok.com product and store pages, tiktok.com/view links, affiliate share links, and vt.tiktok.com short links. Costs 1 credit.\",\n z.object({ url: str(\"A TikTok Shop product or store URL, affiliate share link, or vt.tiktok.com short link.\") }),\n (i) => client.tiktokShop.resolve(i)\n )\n );\n }\n\n if (all || enableInstagram) {\n tools.push(\n tool(\n \"INSTAGRAM_PROFILE\",\n \"Scavio Instagram Profile\",\n \"Fetch an Instagram profile by username or user id. Costs 1 credit.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n }),\n (i) => client.instagram.profile(i)\n ),\n tool(\n \"INSTAGRAM_USER_POSTS\",\n \"Scavio Instagram User Posts\",\n \"List an Instagram user's posts. Costs 2 credits per page.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of posts to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userPosts(i)\n ),\n tool(\n \"INSTAGRAM_USER_REELS\",\n \"Scavio Instagram User Reels\",\n \"List an Instagram user's reels. Costs 1 credit (2 the first time a username is looked up).\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of reels to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userReels(i)\n ),\n tool(\n \"INSTAGRAM_USER_TAGGED\",\n \"Scavio Instagram User Tagged\",\n \"List posts an Instagram user is tagged in. Costs 1 credit (2 the first time a username is looked up).\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of tagged posts to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userTagged(i)\n ),\n tool(\n \"INSTAGRAM_USER_STORIES\",\n \"Scavio Instagram User Stories\",\n \"Fetch an Instagram user's current stories. Costs 2 credits.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n }),\n (i) => client.instagram.userStories(i)\n ),\n tool(\n \"INSTAGRAM_POST\",\n \"Scavio Instagram Post\",\n \"Fetch an Instagram post by URL, media id, or shortcode. Costs 2 credits.\",\n z.object({\n url: ostr(\"Post URL. Provide one of url, media_id, or shortcode.\"),\n media_id: ostr(\"Post media id. Provide one of url, media_id, or shortcode.\"),\n shortcode: ostr(\"Post shortcode. Provide one of url, media_id, or shortcode.\"),\n }),\n (i) => client.instagram.post(i)\n ),\n tool(\n \"INSTAGRAM_POST_COMMENTS\",\n \"Scavio Instagram Post Comments\",\n \"List comments on an Instagram post by shortcode or URL. Costs 2 credits per page.\",\n z.object({\n shortcode: ostr(\"Post shortcode. Provide this or url.\"),\n url: ostr(\"Post URL. Provide this or shortcode.\"),\n cursor: ostr(\"Pagination cursor.\"),\n sort_order: ostr(\"Comment sort order.\"),\n }),\n (i) => client.instagram.postComments(i as SdkOpts<typeof client.instagram.postComments>)\n ),\n tool(\n \"INSTAGRAM_COMMENT_REPLIES\",\n \"Scavio Instagram Comment Replies\",\n \"List replies to an Instagram post comment. Costs 2 credits.\",\n z.object({\n media_id: str(\"Post media id.\"),\n comment_id: str(\"Parent comment id.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.commentReplies(i)\n ),\n tool(\n \"INSTAGRAM_SEARCH_USERS\",\n \"Scavio Instagram Search Users\",\n \"Search Instagram users by keyword. Costs 2 credits; a request with a cursor costs 8.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.searchUsers(i)\n ),\n tool(\n \"INSTAGRAM_SEARCH_HASHTAGS\",\n \"Scavio Instagram Search Hashtags\",\n \"Search Instagram hashtags by keyword. Costs 2 credits; a request with a cursor costs 8.\",\n z.object({\n keyword: str(\"Search keyword.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.searchHashtags(i)\n ),\n tool(\n \"INSTAGRAM_USER_FOLLOWERS\",\n \"Scavio Instagram User Followers\",\n \"List an Instagram user's followers. Costs 2 credits per page.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of followers to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userFollowers(i)\n ),\n tool(\n \"INSTAGRAM_USER_FOLLOWINGS\",\n \"Scavio Instagram User Followings\",\n \"List the accounts an Instagram user follows. Costs 2 credits per page.\",\n z.object({\n username: ostr(\"Instagram username. Provide this or user_id.\"),\n user_id: ostr(\"Instagram user id. Provide this or username.\"),\n count: onum(\"Number of followings to return.\"),\n cursor: ostr(\"Pagination cursor.\"),\n }),\n (i) => client.instagram.userFollowings(i)\n )\n );\n }\n\n // X (Twitter): 11 endpoints, 1 credit each. The keyword field on search is\n // `search`, not `query`. search_type values are Capitalized while the comment\n // `rank` values are lowercase - that asymmetry is upstream's, not a typo.\n if (all || enableX) {\n tools.push(\n tool(\n \"X_SEARCH\",\n \"Scavio X Search\",\n \"Search X (Twitter) posts. Returns data.timeline with next_cursor, prev_cursor and has_more. Costs 1 credit.\",\n z.object({\n search: str(\"Search query (1-500 characters). The field is 'search', not 'query'.\"),\n search_type: ostr(\"Result category (Capitalized): 'Top' (default), 'Latest', 'People', 'Photos', or 'Videos'.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.search(i as SdkOpts<typeof client.x.search>)\n ),\n tool(\n \"X_TWEET\",\n \"Scavio X Tweet\",\n \"Fetch one X post by id. Returns the tweet object plus reply_to, in_reply_to_screen_name, in_reply_to_status_id, in_reply_to_user_id and sensitive. Costs 1 credit.\",\n z.object({ tweet_id: str(\"Numeric post id as a string, e.g. '1808168603721650364'.\") }),\n (i) => client.x.tweet(i)\n ),\n tool(\n \"X_TWEET_COMMENTS\",\n \"Scavio X Tweet Comments\",\n \"List replies to an X post. Returns data.timeline with next_cursor, prev_cursor and has_more. rank switches the upstream feed: 'latest' is chronological, 'top' is ranked. Costs 1 credit.\",\n z.object({\n tweet_id: str(\"Numeric post id as a string.\"),\n rank: ostr(\"Reply ordering (lowercase): 'top' (default, ranked) or 'latest' (chronological).\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.tweetComments(i as SdkOpts<typeof client.x.tweetComments>)\n ),\n tool(\n \"X_TWEET_RETWEETERS\",\n \"Scavio X Tweet Retweeters\",\n \"List the accounts that reposted an X post. Returns data.retweeters with next_cursor and has_more. Costs 1 credit.\",\n z.object({\n tweet_id: str(\"Numeric post id as a string.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.tweetRetweeters(i)\n ),\n tool(\n \"X_USER\",\n \"Scavio X User\",\n \"Fetch an X profile by handle: followers_count, friends_count, statuses_count, media_count, blue_verified, location, website, avatar, header_image and pinned_tweet_ids. Costs 1 credit.\",\n z.object({ screen_name: str(\"An X handle WITHOUT the @, e.g. 'elonmusk'.\") }),\n (i) => client.x.user(i)\n ),\n tool(\n \"X_USER_TWEETS\",\n \"Scavio X User Tweets\",\n \"List an X user's posts. Returns data.timeline plus pinned and user; there is no has_more on this endpoint, so page on next_cursor. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userTweets(i)\n ),\n tool(\n \"X_USER_REPLIES\",\n \"Scavio X User Replies\",\n \"List an X user's replies. Returns data.timeline with next_cursor and prev_cursor; no has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userReplies(i)\n ),\n tool(\n \"X_USER_MEDIA\",\n \"Scavio X User Media\",\n \"List an X user's posts that carry photos or videos. Returns data.timeline with next_cursor and prev_cursor; no has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userMedia(i)\n ),\n tool(\n \"X_USER_FOLLOWERS\",\n \"Scavio X User Followers\",\n \"List an X user's followers. Returns data.followers with followers_count, next_cursor and has_more. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userFollowers(i)\n ),\n tool(\n \"X_USER_FOLLOWINGS\",\n \"Scavio X User Followings\",\n \"List the accounts an X user follows. The response array is data.following (singular), not followings, and there is no following_count. Costs 1 credit.\",\n z.object({\n screen_name: str(\"An X handle WITHOUT the @.\"),\n cursor: ostr(\"Pagination cursor from a prior response.\"),\n }),\n (i) => client.x.userFollowings(i)\n ),\n tool(\n \"X_TRENDING\",\n \"Scavio X Trending\",\n \"List what is trending on X for one country. Returns data.trends with no cursor and no has_more. Costs 1 credit.\",\n z.object({ country: ostr(\"Country NAME, not an ISO code, e.g. 'UnitedStates' (the default).\") }),\n (i) => client.x.trending(i)\n )\n );\n }\n\n // LinkedIn: 9 live endpoints on three credit tiers - 1 for person, person/about,\n // company and post; 10 for the feeds, job search and post comments; 30 for job,\n // the most expensive endpoint in the API. The five retired endpoints\n // (person/contact, company/people, company/jobs, search/people, search/posts)\n // return 410 unbilled and are deliberately NOT exposed: an agent-facing tool\n // that can only fail is worse than no tool.\n if (all || enableLinkedin) {\n tools.push(\n tool(\n \"LINKEDIN_PERSON\",\n \"Scavio LinkedIn Person\",\n \"Fetch a full LinkedIn profile: headline, about, location, follower and connection counts, current_company, experiences, educations, honors_and_awards, bio_links and similar profiles. Costs 1 credit.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle, e.g. 'williamhgates'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n }),\n (i) => client.linkedin.person(i)\n ),\n tool(\n \"LINKEDIN_PERSON_ABOUT\",\n \"Scavio LinkedIn Person About\",\n \"The about-only slice of a LinkedIn profile: about, headline, education_summary, experiences, educations, honors_and_awards and bio_links. Same upstream call as LINKEDIN_PERSON, shaped down. Costs 1 credit.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n }),\n (i) => client.linkedin.personAbout(i)\n ),\n tool(\n \"LINKEDIN_PERSON_POSTS\",\n \"Scavio LinkedIn Person Posts\",\n \"A member's LinkedIn feed - their own posts, or posts they commented on or reacted to via type. 50 per page; advance with next_cursor. Costs 10 credits.\",\n z.object({\n username: ostr(\"Public identifier / vanity handle. Provide this or url.\"),\n url: ostr(\"Full LinkedIn profile URL. Provide this or username.\"),\n type: ostr(\"Which feed: 'posts' (default), 'comments' (posts they commented on), or 'reactions' (posts they reacted to).\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.personPosts(i as SdkOpts<typeof client.linkedin.personPosts>)\n ),\n tool(\n \"LINKEDIN_COMPANY\",\n \"Scavio LinkedIn Company\",\n \"Fetch a LinkedIn company profile: description, website, industries, specialties, employee and follower counts, headquarters, locations, similar and affiliated companies, and featured_employees (a 4-6 person sample, the documented substitute for the retired employee directory). Costs 1 credit.\",\n z.object({\n company: ostr(\"Company universal name / slug, e.g. 'microsoft'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn company URL. Provide this or company.\"),\n }),\n (i) => client.linkedin.company(i)\n ),\n tool(\n \"LINKEDIN_COMPANY_POSTS\",\n \"Scavio LinkedIn Company Posts\",\n \"Recent posts from a LinkedIn company page, 50 per page; advance with next_cursor. There is no type selector here - that is person-only. Costs 10 credits.\",\n z.object({\n company: ostr(\"Company universal name / slug. Provide this or url.\"),\n url: ostr(\"Full LinkedIn company URL. Provide this or company.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.companyPosts(i)\n ),\n tool(\n \"LINKEDIN_SEARCH_JOBS\",\n \"Scavio LinkedIn Search Jobs\",\n \"Search LinkedIn job listings, 25 per page; advance with next_cursor. Upstream rotates its result set so pages overlap - dedupe by job id. Costs 10 credits.\",\n z.object({\n search: str(\"Search keyword, e.g. 'software engineer'. The field is 'search', not 'query'.\"),\n location: ostr(\"Geographic filter; omit to search everywhere.\"),\n cursor: ostr(\"Opaque cursor from a prior response's next_cursor.\"),\n }),\n (i) => client.linkedin.searchJobs(i)\n ),\n tool(\n \"LINKEDIN_JOB\",\n \"Scavio LinkedIn Job\",\n \"Full detail for one LinkedIn job listing, including the hiring company. The most expensive endpoint in the API - about 1 in 5 ids from LINKEDIN_SEARCH_JOBS has no detail record upstream and answers 404 unbilled, so skip rather than retry. Costs 30 credits.\",\n z.object({\n job_id: ostr(\"Job listing id, e.g. '4415427228'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn job URL. Provide this or job_id.\"),\n }),\n (i) => client.linkedin.job(i)\n ),\n tool(\n \"LINKEDIN_POST\",\n \"Scavio LinkedIn Post\",\n \"Full detail for one LinkedIn post: text, media, hashtags, tagged companies and people, reaction and comment counts, author, and its top visible comments. Costs 1 credit.\",\n z.object({\n post_id: ostr(\"Post id or activity urn, e.g. '7488618410256523265'. Provide this or url.\"),\n url: ostr(\"Full LinkedIn post URL. Provide this or post_id.\"),\n }),\n (i) => client.linkedin.post(i)\n ),\n tool(\n \"LINKEDIN_POST_COMMENTS\",\n \"Scavio LinkedIn Post Comments\",\n \"Comments on a LinkedIn post with their replies. This is the only LinkedIn endpoint paginated by a 1-based integer page rather than a cursor, and page size varies upstream - keep paging until a page comes back empty. Costs 10 credits.\",\n z.object({\n post_id: ostr(\"Post id or activity urn. Provide this or url.\"),\n url: ostr(\"Full LinkedIn post URL. Provide this or post_id.\"),\n page: onum(\"1-based page number (default 1). Page size varies, so page until empty.\"),\n }),\n (i) => client.linkedin.postComments(i)\n )\n );\n }\n\n // Threads is BODY-PRICED: 2 credits addressed by user_id, 4 by username,\n // because the handle has to be resolved through people search first.\n if (all || enableThreads) {\n tools.push(\n tool(\n \"THREADS_PROFILE\",\n \"Scavio Threads Profile\",\n \"Profile details for a Threads user. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total): the upstream handle lookup is down, so the handle is resolved through people search first. Pass user_id instead to avoid that.\"),\n }),\n (i) => client.threads.profile(i as SdkOpts<typeof client.threads.profile>)\n ),\n tool(\n \"THREADS_USER_POSTS\",\n \"Scavio Threads User Posts\",\n \"A user's Threads posts, cursor-paginated via next_cursor. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total) because the handle has to be resolved through people search first.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.userPosts(i as SdkOpts<typeof client.threads.userPosts>)\n ),\n tool(\n \"THREADS_USER_REPLIES\",\n \"Scavio Threads User Replies\",\n \"A user's Threads replies, cursor-paginated via next_cursor. Costs 2 credits addressed by user_id and 4 credits addressed by username - the price is a function of the request body, not a constant for the route; pass user_id whenever you have it.\",\n z.object({\n user_id: ostr(\"Numeric Threads user id, e.g. '63625256886'. The cheap path: 2 credits.\"),\n username: ostr(\"Threads handle without the @ (1-60 characters). Costs 2 extra credits (4 total) because the handle has to be resolved through people search first.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.userReplies(i as SdkOpts<typeof client.threads.userReplies>)\n ),\n tool(\n \"THREADS_POST\",\n \"Scavio Threads Post\",\n \"A single Threads post, addressed by post_id or by its threads.net URL. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n post_id: ostr(\"Threads post id, e.g. '3349029093483693129'.\"),\n url: ostr(\"Full threads.net post URL (e.g. 'https://www.threads.net/@natgeo/post/C8xY'), as an alternative to post_id.\"),\n }),\n (i) => client.threads.post(i as SdkOpts<typeof client.threads.post>)\n ),\n tool(\n \"THREADS_POST_COMMENTS\",\n \"Scavio Threads Post Comments\",\n \"Replies to a Threads post, cursor-paginated via next_cursor. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n post_id: str(\"Threads post id, e.g. '3349029093483693129'.\"),\n cursor: ostr(\"Pagination cursor from a prior response's next_cursor. Omit for the first page.\"),\n }),\n (i) => client.threads.postComments(i as SdkOpts<typeof client.threads.postComments>)\n ),\n tool(\n \"THREADS_SEARCH_USERS\",\n \"Scavio Threads Search Users\",\n \"Search Threads profiles by name or handle. This is the only search Threads exposes - there is no post or content search - and it returns a single unpaginated page. Costs 2 credits: Threads is body-priced by identifier, but this endpoint has no username form, so it is always 2.\",\n z.object({\n query: str(\"Name or handle to search for (1-200 characters).\"),\n }),\n (i) => client.threads.searchUsers(i as SdkOpts<typeof client.threads.searchUsers>)\n )\n );\n }\n\n // Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\n // Kwai international (kwai.com) is not served upstream; only kuaishou.com links\n // resolve. Upstream hides failures inside HTTP 200, so check the payload.\n if (all || enableKuaishou) {\n tools.push(\n tool(\n \"KUAISHOU_PROFILE\",\n \"Scavio Kuaishou Profile\",\n \"Profile details for a Kuaishou user. Costs 10 credits, the dearest single-object call on the platform: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n }),\n (i) => client.kuaishou.profile(i as SdkOpts<typeof client.kuaishou.profile>)\n ),\n tool(\n \"KUAISHOU_USER_POSTS\",\n \"Scavio Kuaishou User Posts\",\n \"A Kuaishou user's top posts, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.userPosts(i as SdkOpts<typeof client.kuaishou.userPosts>)\n ),\n tool(\n \"KUAISHOU_USER_LIVE\",\n \"Scavio Kuaishou User Live\",\n \"A Kuaishou user's current live-stream status. Not paginated. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n user_id: str(\"Kuaishou user id (non-empty); get one from user_resolve or search_users.\"),\n }),\n (i) => client.kuaishou.userLive(i as SdkOpts<typeof client.kuaishou.userLive>)\n ),\n tool(\n \"KUAISHOU_USER_RESOLVE\",\n \"Scavio Kuaishou User Resolve\",\n \"Turns a Kuaishou share link into a user id. Only kuaishou.com and v.kuaishou.com links are accepted; Kwai international (kwai.com) is not served upstream. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n share_link: str(\"A kuaishou.com or v.kuaishou.com URL; kwai.com links are rejected.\"),\n }),\n (i) => client.kuaishou.userResolve(i as SdkOpts<typeof client.kuaishou.userResolve>)\n ),\n tool(\n \"KUAISHOU_VIDEO\",\n \"Scavio Kuaishou Video\",\n \"A single Kuaishou video by photo id or URL. Provide photo_id or url. Costs 2 credits: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: ostr(\"Kuaishou photo (video) id, non-empty.\"),\n url: ostr(\"Full kuaishou.com video URL, as an alternative to photo_id.\"),\n }),\n (i) => client.kuaishou.video(i as SdkOpts<typeof client.kuaishou.video>)\n ),\n tool(\n \"KUAISHOU_VIDEO_COMMENTS\",\n \"Scavio Kuaishou Video Comments\",\n \"Comments on a Kuaishou video, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: str(\"Kuaishou photo (video) id, non-empty.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.videoComments(i as SdkOpts<typeof client.kuaishou.videoComments>)\n ),\n tool(\n \"KUAISHOU_COMMENT_REPLIES\",\n \"Scavio Kuaishou Comment Replies\",\n \"Replies under a root comment on a Kuaishou video, cursor-paginated via next_cursor; count sizes the page (1-50). Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_id: str(\"Kuaishou photo (video) id, non-empty.\"),\n root_comment_id: str(\"Id of the top-level comment whose replies you want, from video_comments.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n count: onum(\"Replies per page, 1-50. Omit to use the upstream default.\"),\n }),\n (i) => client.kuaishou.commentReplies(i as SdkOpts<typeof client.kuaishou.commentReplies>)\n ),\n tool(\n \"KUAISHOU_VIDEOS_BATCH\",\n \"Scavio Kuaishou Videos Batch\",\n \"Several Kuaishou videos in one call, hard-capped at 20 photo ids. Costs 40 credits, the dearest call on the platform: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n photo_ids: arrstr(\"Kuaishou photo (video) ids, 1-20 per call; more than 20 is rejected.\"),\n }),\n (i) => client.kuaishou.videosBatch(i as SdkOpts<typeof client.kuaishou.videosBatch>)\n ),\n tool(\n \"KUAISHOU_SEARCH\",\n \"Scavio Kuaishou Search\",\n \"Mixed-result search across Kuaishou, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.search(i as SdkOpts<typeof client.kuaishou.search>)\n ),\n tool(\n \"KUAISHOU_SEARCH_VIDEOS\",\n \"Scavio Kuaishou Search Videos\",\n \"Kuaishou video search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchVideos(i as SdkOpts<typeof client.kuaishou.searchVideos>)\n ),\n tool(\n \"KUAISHOU_SEARCH_USERS\",\n \"Scavio Kuaishou Search Users\",\n \"Kuaishou user search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchUsers(i as SdkOpts<typeof client.kuaishou.searchUsers>)\n ),\n tool(\n \"KUAISHOU_SEARCH_LIVE\",\n \"Scavio Kuaishou Search Live\",\n \"Kuaishou live-stream search results, cursor-paginated via next_cursor. Costs 10 credits per page: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n keyword: str(\"Search keyword, 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.searchLive(i as SdkOpts<typeof client.kuaishou.searchLive>)\n ),\n tool(\n \"KUAISHOU_TAG_FEED\",\n \"Scavio Kuaishou Tag Feed\",\n \"Posts under a Kuaishou hashtag, cursor-paginated via next_cursor. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n tag: str(\"Hashtag text without the leading '#', 1-200 characters.\"),\n cursor: ostr(\"Opaque next_cursor from a prior response; omit for the first page.\"),\n }),\n (i) => client.kuaishou.tagFeed(i as SdkOpts<typeof client.kuaishou.tagFeed>)\n ),\n tool(\n \"KUAISHOU_TRENDING\",\n \"Scavio Kuaishou Trending\",\n \"Kuaishou hot / live / shopping / brand / music leaderboards. One board per call, not paginated. Costs 1 credit: Kuaishou is priced PER ENDPOINT (1, 2, 10 or 40), never per platform.\",\n z.object({\n board: ostr(\"Leaderboard to return; defaults to 'hot' when omitted. Accepted values: 'hot', 'live', 'shopping', 'brand', 'music'.\"),\n }),\n (i) => client.kuaishou.trending(i as SdkOpts<typeof client.kuaishou.trending>)\n )\n );\n }\n\n if (all || enableEbay) {\n tools.push(\n tool(\n \"EBAY_SEARCH\",\n \"Scavio eBay Search\",\n \"Search live or SOLD eBay listings: price, condition, bids, shipping, seller, feedback. Provide query or seller; per_page accepts only 60, 120 or 240. Costs 1 credit.\",\n z.object({\n query: ostr(\"Keyword to search (1-500 characters). Optional: a seller-only search pages that seller's whole catalogue.\"),\n seller: ostr(\"Restrict results to one seller's listings (1-64 characters), as in ebay.com/usr/<name>. Can be sent with no query.\"),\n page: onum(\"Results page, 1-based.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. eBay's 'Distance: nearest first' is deliberately unsupported (it ranks against our proxy exit, not the caller). Accepted values: 'best_match', 'ending_soonest', 'newly_listed', 'price_low', 'price_high'.\"),\n min_price: onum(\"Minimum price, inclusive. Must be 0 or greater.\"),\n max_price: onum(\"Maximum price, inclusive. Must be 0 or greater.\"),\n condition: ostr(\"Item condition filter. 'refurbished' is eBay's parent condition, not one of its three graded tiers. Accepted values: 'new', 'open_box', 'refurbished', 'used', 'for_parts'.\"),\n buying_format: ostr(\"Listing format: auction, fixed price (buy_it_now), or fixed price accepting offers (best_offer).\"),\n free_shipping: obool(\"Only listings with free shipping.\"),\n sold: obool(\"Search completed listings that actually SOLD, for price research. eBay publishes no headline count on this view, so total_results is null.\"),\n category_id: ostr(\"eBay category id; must be numeric (e.g. '112529'). An unrecognised id returns the UNFILTERED set under a 200.\"),\n per_page: onum(\"Listings per page: 60, 120 or 240 only. Defaults to 60; eBay silently falls back to 60 for anything else.\"),\n }),\n (i) => client.ebay.search(i as SdkOpts<typeof client.ebay.search>)\n ),\n tool(\n \"EBAY_PRODUCT\",\n \"Scavio eBay Product\",\n \"One eBay listing in full: price, condition, images, item specifics, shipping, returns, auction state, seller. Costs 1 credit.\",\n z.object({\n item_id: str(\"eBay item number (e.g. '168591664725'), or a full ebay.com/itm/... listing URL; tracking parameters on a pasted URL are discarded.\"),\n }),\n (i) => client.ebay.product(i as SdkOpts<typeof client.ebay.product>)\n ),\n tool(\n \"EBAY_SELLER\",\n \"Scavio eBay Seller\",\n \"eBay seller profile card: store name, feedback score and %, items sold, followers, location, categories. Profile only: page a catalogue with search(seller=...). Costs 1 credit.\",\n z.object({\n seller: str(\"eBay username as it appears in ebay.com/usr/<name> (1-64 characters), which is what seller_name on a search or product result returns.\"),\n }),\n (i) => client.ebay.seller(i as SdkOpts<typeof client.ebay.seller>)\n )\n );\n }\n\n if (all || enableTarget) {\n tools.push(\n tool(\n \"TARGET_SEARCH\",\n \"Scavio Target Search\",\n \"Search Target.com, the US retailer: prices, ratings, badges and promotions. Up to 28 results per page; rendered upstream, so expect around 9 seconds. Costs 1 credit.\",\n z.object({\n keyword: str(\"Search keyword (1-500 characters).\"),\n page: onum(\"Results page, 1-based.\"),\n count: onum(\"Results per page, 1-28. Defaults to 24; Target rejects anything above 28 outright.\"),\n sort: ostr(\"Result sort order. Defaults to 'relevance'. Accepted values: 'relevance', 'featured', 'price_low', 'price_high', 'rating_high', 'best_seller', 'newest'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991', the store target.com uses with no store context.\"),\n }),\n (i) => client.target.search(i as SdkOpts<typeof client.target.search>)\n ),\n tool(\n \"TARGET_CATEGORY\",\n \"Scavio Target Category\",\n \"Products in a Target category, same shape as search plus the category breadcrumb. Up to 28 per page; the slowest Target endpoint at around 37 seconds. Costs 1 credit.\",\n z.object({\n category_id: str(\"Target category id: the segment after 'N-' in a target.com /c/ URL (target.com/c/apple/-/N-5xtg6 -> '5xtg6').\"),\n page: onum(\"Results page, 1-based.\"),\n count: onum(\"Results per page, 1-28. Defaults to 24; Target rejects anything above 28 outright.\"),\n sort: ostr(\"Result sort order. Defaults to 'relevance'. Accepted values: 'relevance', 'featured', 'price_low', 'price_high', 'rating_high', 'best_seller', 'newest'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.category(i as SdkOpts<typeof client.target.category>)\n ),\n tool(\n \"TARGET_PRODUCT\",\n \"Scavio Target Product\",\n \"Target product details by TCIN: price, rating, images, specifications, variants, return policy, fulfillment. seller_id/seller_name are null for stock sold by Target. Costs 1 credit.\",\n z.object({\n tcin: str(\"Target catalog id (tcin, e.g. '1010453160'). A colour/size child tcin is answered by its variation parent, with the child present in 'variants'.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.product(i as SdkOpts<typeof client.target.product>)\n ),\n tool(\n \"TARGET_REVIEWS\",\n \"Scavio Target Reviews\",\n \"Target reviews with the rating breakdown, per-attribute averages and guest photos. 8 review bodies maximum and no paging; expect around 40 seconds. Costs 1 credit.\",\n z.object({\n tcin: str(\"Target catalog id (tcin, e.g. '1010453160').\"),\n limit: onum(\"Trim the returned reviews to at most this many (1 or greater). Target publishes 8 anonymously and offers no paging, so this only trims.\"),\n store_id: ostr(\"Numeric Target store id whose prices and availability the response reflects. Defaults to '3991'.\"),\n }),\n (i) => client.target.reviews(i as SdkOpts<typeof client.target.reviews>)\n )\n );\n }\n\n if (all || enableHomeDepot) {\n tools.push(\n tool(\n \"HOME_DEPOT_SEARCH\",\n \"Scavio Home Depot Search\",\n \"Search Home Depot: price and promotions, brand and model, ratings, badges, per-store pickup/delivery. Page size is fixed at 12 and cannot be changed. Costs 2 credits.\",\n z.object({\n query: str(\"Search keyword (1-500 characters).\"),\n page: onum(\"Results page, 1-based. Home Depot serves 12 products per page and offers no way to change that, so paging is the only way to read further.\"),\n sort_by: ostr(\"Result sort order. Defaults to 'best_match'. Closed enum: Home Depot answers an unknown sort with an empty page that is still billed. 'Newest' is absent - it is rejected on keyword search. Accepted values: 'best_match', 'top_sellers', 'top_rated', 'price_low', 'price_high'.\"),\n min_price: onum(\"Minimum price, inclusive. Must be 0 or greater.\"),\n max_price: onum(\"Maximum price, inclusive. Must be 0 or greater.\"),\n }),\n (i) => client.homeDepot.search(i as SdkOpts<typeof client.homeDepot.search>)\n ),\n tool(\n \"HOME_DEPOT_PRODUCT\",\n \"Scavio Home Depot Product\",\n \"Full Home Depot item detail: pricing, images and videos, spec table, dimensions, bullets, documents, return policy. Carries a 10-review preview only. Costs 2 credits.\",\n z.object({\n item_id: str(\"Home Depot item id (e.g. '325479354'), or a full homedepot.com/p/... product URL; tracking parameters on a pasted URL are discarded.\"),\n }),\n (i) => client.homeDepot.product(i as SdkOpts<typeof client.homeDepot.product>)\n ),\n tool(\n \"HOME_DEPOT_REVIEWS\",\n \"Scavio Home Depot Reviews\",\n \"One page of full Home Depot review bodies, the rating distribution, per-attribute ratings, photos and seller responses. 30 reviews per page. Costs 2 credits.\",\n z.object({\n item_id: str(\"Home Depot item id (e.g. '325479354'), or a full homedepot.com/p/... product URL; tracking parameters on a pasted URL are discarded.\"),\n page: onum(\"Reviews page, 1-based. 30 reviews per page; 'total_pages' in the response is the last one that exists, and asking past it is a 404.\"),\n }),\n (i) => client.homeDepot.reviews(i as SdkOpts<typeof client.homeDepot.reviews>)\n )\n );\n }\n\n if (all || enableZillow) {\n tools.push(\n tool(\n \"ZILLOW_SEARCH\",\n \"Scavio Zillow Search\",\n \"Zillow listings in a region: price, beds, baths, living area, Zestimate, coordinates, images, days on market. A bare ZIP works alone but cannot be combined with a filter or a sort. Costs 1 credit.\",\n z.object({\n location: str(\"Region to search (1-200 characters): a Zillow slug ('austin-tx'), a human form ('Austin, TX'), a ZIP, or a pasted zillow.com search URL. A ZIP works alone but cannot be combined with a filter or sort; an unresolvable region is a 404.\"),\n listing_status: ostr(\"Which listings to return. Defaults to 'for_sale'. Accepted values: 'for_sale', 'for_rent', 'sold'.\"),\n page: onum(\"Results page, 1-based.\"),\n sort: ostr(\"Result sort order. Sorts that rank against a signed-in profile (saved/featured/personalised) are unsupported - we are never signed in. Accepted values: 'relevance', 'recommended', 'newest', 'price_low', 'price_high', 'payment_low', 'payment_high', 'beds', 'baths', 'sqft', 'lot_size', 'zestimate_low', 'zestimate_high', 'recent_change'.\"),\n min_price: onum(\"Minimum price, inclusive (0 or greater). On listing_status='for_rent' this is MONTHLY RENT - Zillow files rent under its payment filter.\"),\n max_price: onum(\"Maximum price, inclusive (0 or greater). On listing_status='for_rent' this is MONTHLY RENT.\"),\n beds_min: onum(\"Minimum bedrooms; whole number, 0 or greater.\"),\n beds_max: onum(\"Maximum bedrooms; whole number, 0 or greater.\"),\n baths_min: onum(\"Minimum bathrooms, 0 or greater. Half-baths are allowed (1.5).\"),\n baths_max: onum(\"Maximum bathrooms, 0 or greater. Half-baths are allowed (1.5).\"),\n sqft_min: onum(\"Minimum living area in square feet; whole number, 0 or greater.\"),\n sqft_max: onum(\"Maximum living area in square feet; whole number, 0 or greater.\"),\n lot_size_min: onum(\"Minimum lot size in square feet; whole number, 0 or greater.\"),\n lot_size_max: onum(\"Maximum lot size in square feet; whole number, 0 or greater.\"),\n year_built_min: onum(\"Earliest year built; whole number, 0 or greater.\"),\n year_built_max: onum(\"Latest year built; whole number, 0 or greater.\"),\n max_hoa: onum(\"Maximum monthly HOA fee in dollars, 0 or greater.\"),\n home_type: ostr(\"Property type filter. Accepted values: 'houses', 'townhomes', 'multi_family', 'condos', 'apartments', 'manufactured', 'lots_land'.\"),\n days_on_zillow: ostr(\"Listed - or, with listing_status='sold', sold - within the last N days. Closed enum: an unrecognised value returns the UNFILTERED set under a 200. Accepted values: '1', '7', '14', '30', '90', '6m', '12m', '24m', '36m'.\"),\n keywords: ostr(\"Free-text match against the listing description (1-200 characters).\"),\n has_pool: obool(\"Only listings with a pool.\"),\n has_garage: obool(\"Only listings with a garage.\"),\n has_air_conditioning: obool(\"Only listings with air conditioning.\"),\n is_waterfront: obool(\"Only waterfront listings.\"),\n has_basement: obool(\"Only listings with a basement.\"),\n is_new_construction: obool(\"Only new-construction listings.\"),\n has_open_house: obool(\"Only listings with an upcoming open house.\"),\n price_reduced: obool(\"Only listings whose price was reduced.\"),\n is_3d_tour: obool(\"Only listings with a 3D tour.\"),\n }),\n (i) => client.zillow.search(i as SdkOpts<typeof client.zillow.search>)\n ),\n tool(\n \"ZILLOW_PROPERTY\",\n \"Scavio Zillow Property\",\n \"Full Zillow listing: price and price history, Zestimate, tax history, RESO facts, rooms, schools, open houses, photos. Rental buildings return floor plans instead. Costs 1 credit.\",\n z.object({\n zpid: str(\"Zillow property id (e.g. '29414894'), a full /homedetails/ URL, or a rental building URL (zillow.com/apartments/...). The building form is required for buildings: they have no zpid a caller can see.\"),\n }),\n (i) => client.zillow.property(i as SdkOpts<typeof client.zillow.property>)\n ),\n tool(\n \"ZILLOW_AGENT_REVIEWS\",\n \"Scavio Zillow Agent Reviews\",\n \"A Zillow AGENT's profile and reviews: rating, bodies with sub-ratings, specialties, licenses, service areas, sales counts. Zillow server-renders the first five. Costs 1 credit.\",\n z.object({\n screen_name: str(\"Zillow agent profile screen name as it appears in zillow.com/profile/<name>/ (1-200 characters, may contain spaces), or a full profile URL.\"),\n }),\n (i) => client.zillow.agentReviews(i as SdkOpts<typeof client.zillow.agentReviews>)\n )\n );\n }\n\n if (all || enableBooking) {\n tools.push(\n tool(\n \"BOOKING_SEARCH\",\n \"Scavio Booking.com Search\",\n \"Booking.com properties for a destination and stay: live nightly price, review score, star rating, location, room type, deal badges. 25 properties per page. Provide destination or dest_id. Costs 1 credit.\",\n z.object({\n destination: ostr(\"Destination to search, e.g. 'Paris' (1-200 characters). Required unless dest_id is given.\"),\n dest_id: ostr(\"Numeric Booking.com destination id, as an alternative to destination.\"),\n dest_type: ostr(\"What dest_id refers to. Requires dest_id and is rejected without it, because Booking silently ignores a lone dest_type. Accepted values: 'city', 'region', 'country', 'district', 'landmark', 'airport', 'hotel'.\"),\n page: onum(\"Results page, 1-based. 25 properties per page, 1 credit each.\"),\n sort_by: ostr(\"Result sort order (default 'popularity'). Accepted values: 'popularity', 'price_low', 'price_high', 'stars_high', 'stars_low', 'stars_and_price', 'distance', 'review_score'.\"),\n min_price: onum(\"Minimum price PER NIGHT in `currency`, >= 0. Must not exceed max_price.\"),\n max_price: onum(\"Maximum price PER NIGHT in `currency`, >= 0.\"),\n stars: oarrnum(\"Star ratings to include, each 1-5, 1-5 values, OR'd together (e.g. [4, 5]).\"),\n min_review_score: ostr(\"Minimum guest review score. Only '6', '7', '8' and '9' exist upstream; any other threshold is silently dropped.\"),\n property_type: ostrnum(\"Accommodation type by name, or a raw numeric Booking accommodation-type id (>= 1). Accepted values: 'apartments', 'hostels', 'hotels', 'motels', 'resorts', 'bed_and_breakfasts', 'villas', 'campgrounds', 'vacation_homes', 'lodges', 'homestays'.\"),\n free_cancellation: obool(\"Only properties offering free cancellation.\"),\n no_prepayment: obool(\"Only properties that take no prepayment.\"),\n breakfast_included: obool(\"Only rates that include breakfast.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout: a lone checkin is ignored and Booking prices a default range of its own.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Booking prices off the proxy exit and identical requests disagree.\"),\n }),\n (i) => client.booking.search(i as SdkOpts<typeof client.booking.search>)\n ),\n tool(\n \"BOOKING_HOTEL\",\n \"Scavio Booking.com Hotel\",\n \"One Booking.com property in full: rooms and rate plans, facilities, house rules, check-in windows, policies, images, location and review scores, priced for the stay asked for. Chaining the `url` a search row returns is cheaper than a bare slug. Costs 1 credit.\",\n z.object({\n hotel: str(\"Booking.com property URL or the bare page slug (1-500 characters); query params are discarded.\"),\n country_code: ostr(\"Two-letter country code for the property page (default 'us'). Only consulted for a bare slug, where a wrong one is a real, BILLED 404.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout; omitting both prices a two-night range Booking chose, echoed back in the response.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Booking prices off the proxy exit and identical requests disagree.\"),\n }),\n (i) => client.booking.hotel(i as SdkOpts<typeof client.booking.hotel>)\n ),\n tool(\n \"BOOKING_REVIEWS\",\n \"Scavio Booking.com Reviews\",\n \"Booking.com guest reviews for a property with the score breakdown by category and Booking's own praise/complaint summary. No page param: total_count is the whole review history, count is what this response holds. Costs 1 credit.\",\n z.object({\n hotel: str(\"Booking.com property URL or the bare page slug (1-500 characters); query params are discarded.\"),\n country_code: ostr(\"Two-letter country code for the property page (default 'us'). Only consulted for a bare slug, where a wrong one is a real, BILLED 404.\"),\n checkin: ostr(\"Check-in date, YYYY-MM-DD. Must be sent together with checkout; it prices the stay the review page is rendered for.\"),\n checkout: ostr(\"Check-out date, YYYY-MM-DD. Must be later than checkin and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1 (default 2).\"),\n children_ages: oarrnum(\"AGES of accompanying children, each 0-17, max 10 entries. Ages, not a count.\"),\n rooms: onum(\"Rooms required, >= 1 (default 1).\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD').\"),\n }),\n (i) => client.booking.reviews(i as SdkOpts<typeof client.booking.reviews>)\n )\n );\n }\n\n // Tripadvisor is keyed by geo_id + location_id: resolve a name with\n // TRIPADVISOR_LOCATIONS first, or nothing else on the platform is reachable.\n if (all || enableTripadvisor) {\n tools.push(\n tool(\n \"TRIPADVISOR_LOCATIONS\",\n \"Scavio Tripadvisor Locations\",\n \"START HERE: resolve a place or business NAME to the TripAdvisor geo_id / location_id pair every other TripAdvisor endpoint is keyed by. Up to 20 rows. Costs 2 credits.\",\n z.object({\n query: str(\"Place or business name to resolve (1-120 characters).\"),\n limit: onum(\"Rows to return, 1-20 (default 12). Sizes the response only; there is no paging here.\"),\n }),\n (i) => client.tripadvisor.locations(i as SdkOpts<typeof client.tripadvisor.locations>)\n ),\n tool(\n \"TRIPADVISOR_SEARCH\",\n \"Scavio Tripadvisor Search\",\n \"Restaurants, hotels or attractions in a TripAdvisor geo, TripAdvisor-ranked: rating, review count, price band, address, coordinates, phone, hours, Travelers' Choice badge; each row carries the location_id + geo_id pair. 30 locations per page. Provide geo_id or url. Costs 2 credits.\",\n z.object({\n geo_id: ostr(\"TripAdvisor geo id (1-500 characters): 30196, g30196, or a URL carrying one. Required unless url is given.\"),\n category: ostr(\"Listing family to search (default 'restaurants'). Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n page: onum(\"Results page, 1-based. 30 locations per page; a page beyond the last is a 404, not an empty result.\"),\n url: ostr(\"Full tripadvisor.com listing URL (1-500 characters), as an alternative to geo_id; country sites are accepted.\"),\n }),\n (i) => client.tripadvisor.search(i as SdkOpts<typeof client.tripadvisor.search>)\n ),\n tool(\n \"TRIPADVISOR_LOCATION\",\n \"Scavio Tripadvisor Location\",\n \"One TripAdvisor location in full: rating, review histogram and per-aspect sub-ratings, city ranking, price band, cuisines, amenities, address, coordinates, contact, photos, and the FIRST PAGE OF REVIEWS. Provide location_id or url. Costs 2 credits.\",\n z.object({\n location_id: ostr(\"TripAdvisor location id (1-500 characters): 1899234, d1899234, or a full _Review URL. Required unless url is given.\"),\n geo_id: ostr(\"Geo the location sits in; required when location_id is a bare d-id.\"),\n category: ostr(\"Location family (default 'restaurants'); match the location's own type. Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n url: ostr(\"Full tripadvisor.com _Review URL (1-500 characters), as an alternative to location_id.\"),\n }),\n (i) => client.tripadvisor.location(i as SdkOpts<typeof client.tripadvisor.location>)\n ),\n tool(\n \"TRIPADVISOR_REVIEWS\",\n \"Scavio Tripadvisor Reviews\",\n \"A page of TripAdvisor reviews: rating, trip date and type, reviewer home town and contribution count, management response. Page 1 already rides along in location(), so use this to page PAST it; consecutive pages can repeat one review at the boundary, so de-duplicate on review_id. Provide location_id or url. Costs 2 credits.\",\n z.object({\n location_id: ostr(\"TripAdvisor location id (1-500 characters): 1899234, d1899234, or a full _Review URL. Required unless url is given.\"),\n geo_id: ostr(\"Geo the location sits in; required when location_id is a bare d-id.\"),\n category: ostr(\"Location family (default 'restaurants'). It sets the page size, so it must match the location's own type on any page past the first. Accepted values: 'restaurants', 'hotels', 'attractions'.\"),\n url: ostr(\"Full tripadvisor.com _Review URL (1-500 characters), as an alternative to location_id.\"),\n page: onum(\"Reviews page, 1-based. 15 per page for restaurants, 10 for hotels and attractions; past the last page is a 404.\"),\n }),\n (i) => client.tripadvisor.reviews(i as SdkOpts<typeof client.tripadvisor.reviews>)\n )\n );\n }\n\n if (all || enableIndeed) {\n tools.push(\n tool(\n \"INDEED_SEARCH\",\n \"Scavio Indeed Search\",\n \"Indeed job postings: title, employer, rating, location, salary range, job type, benefits, posting age, apply route. 10 postings per page. Provide query or location - a location-only search (every posting in a metro) is valid. Costs 2 credits.\",\n z.object({\n query: ostr(\"Job title, keywords or employer (1-500 characters). Required unless location is given.\"),\n location: ostr(\"City and state, postal code, state, country, or 'Remote' (1-200 characters). Valid on its own with no query.\"),\n page: onum(\"Results page, 1-based. 10 postings per page, 1 call each.\"),\n radius: onum(\"Search radius in miles around location. Closed set: Indeed IGNORES any other value and returns the unfiltered set. Upstream default 50. Accepted values: 0, 5, 10, 15, 25, 35, 50, 100.\"),\n max_age_days: onum(\"Maximum posting age in days. Closed set: Indeed IGNORES any other value and returns postings of every age. Accepted values: 1, 3, 7, 14.\"),\n job_type: ostr(\"Employment type filter. Accepted values: 'full_time', 'part_time', 'contract', 'temporary', 'internship'.\"),\n min_salary: onum(\"Minimum annual salary, >= 0. Filters on INDEED'S OWN ESTIMATE for the role, not a posted figure, so postings publishing no salary still match.\"),\n remote: obool(\"Remote postings only.\"),\n }),\n (i) => client.indeed.search(i as SdkOpts<typeof client.indeed.search>)\n ),\n tool(\n \"INDEED_JOB\",\n \"Scavio Indeed Job\",\n \"One Indeed posting in full: description text and HTML, structured salary, employment types, benefits, geocoded address, employer rating, applicant count, original ATS link. An unknown job key is a real 404 that is still billed. Costs 2 credits.\",\n z.object({\n job_id: str(\"16-hex Indeed job key, or any indeed.com URL carrying jk= (/viewjob, /rc/clk, /pagead/clk).\"),\n }),\n (i) => client.indeed.job(i as SdkOpts<typeof client.indeed.job>)\n ),\n tool(\n \"INDEED_COMPANY\",\n \"Scavio Indeed Company\",\n \"Indeed employer profile: description, industry, HQ, size, revenue, CEO approval, overall and per-category ratings, reported salaries, open roles, locations. An unknown slug is a real 404 that is still billed. Costs 2 credits.\",\n z.object({\n company: str(\"indeed.com/cmp/<slug> slug or a full profile URL (1-200 characters); slugs are untidy, e.g. 'Tata-Consultancy-Services-(tcs)'.\"),\n }),\n (i) => client.indeed.company(i as SdkOpts<typeof client.indeed.company>)\n ),\n tool(\n \"INDEED_COMPANY_REVIEWS\",\n \"Scavio Indeed Company Reviews\",\n \"Indeed employee reviews, 20 per page, with per-category ratings, pros/cons, reviewer job title and location, plus aggregated sentiment and topic/location/job-title breakdowns. Costs 2 credits.\",\n z.object({\n company: str(\"indeed.com/cmp/<slug> slug or a full profile URL (1-200 characters).\"),\n page: onum(\"Reviews page, 1-based. 20 reviews per page.\"),\n }),\n (i) => client.indeed.companyReviews(i as SdkOpts<typeof client.indeed.companyReviews>)\n )\n );\n }\n\n if (all || enableAirbnb) {\n tools.push(\n tool(\n \"AIRBNB_SEARCH\",\n \"Scavio Airbnb Search\",\n \"Airbnb stays: stay-total and per-night price with the full discount ledger, rating and review count, bedrooms/beds/baths, coordinates, badges, images, dates_are_defaulted. 18 listings per page; page and cursor are mutually exclusive. Costs 1 credit.\",\n z.object({\n location: str(\"City, region, ZIP, or a pasted airbnb.com/s/ URL (1-200 characters). An unresolvable location is a 404.\"),\n check_in: ostr(\"Check-in date, YYYY-MM-DD. Must be sent with check_out; omitting both defaults to +30 days and flags dates_are_defaulted in the response.\"),\n check_out: ostr(\"Check-out date, YYYY-MM-DD. Must be later than check_in; defaults to check_in plus 5 nights when omitted.\"),\n adults: onum(\"Adult guests, >= 1.\"),\n children: onum(\"Children aged 2-12, >= 0.\"),\n infants: onum(\"Infants under 2, >= 0.\"),\n pets: onum(\"Pets, >= 0.\"),\n min_price: onum(\"Minimum price for the WHOLE STAY in `currency`, not per night, >= 0. Must not exceed max_price.\"),\n max_price: onum(\"Maximum price for the WHOLE STAY in `currency`, not per night, >= 0.\"),\n room_type: ostr(\"Room type. Validated before the scrape, because an unrecognised value returns the UNFILTERED set under a 200. Accepted values: 'entire_home', 'private_room', 'shared_room', 'hotel_room'.\"),\n min_bedrooms: onum(\"Minimum bedrooms, >= 0.\"),\n min_beds: onum(\"Minimum beds, >= 0.\"),\n min_bathrooms: onum(\"Minimum bathrooms, >= 0.\"),\n superhost: obool(\"Superhost listings only.\"),\n instant_book: obool(\"Instant Book listings only.\"),\n guest_favorite: obool(\"Guest Favorite listings only.\"),\n free_cancellation: obool(\"Listings with free cancellation only.\"),\n amenities: ostr(\"Comma-separated amenities (1-200 characters): wifi, air_conditioning, pool, kitchen, free_parking, washer, self_check_in, tv, or raw numeric Airbnb amenity ids. An unrecognised NAME is rejected before the scrape.\"),\n currency: ostr(\"ISO 4217 currency for prices, 3 letters (default 'USD'). Without it Airbnb prices off the proxy exit and identical requests disagree.\"),\n page: onum(\"Results page, 1-based. 18 listings per page. Cannot be combined with cursor.\"),\n cursor: ostr(\"next_cursor from a previous response (1-500 characters); wins over page, so sending both is rejected.\"),\n }),\n (i) => client.airbnb.search(i as SdkOpts<typeof client.airbnb.search>)\n ),\n tool(\n \"AIRBNB_LISTING\",\n \"Scavio Airbnb Listing\",\n \"One Airbnb listing in full: description, property/room type, capacity and room counts, the complete grouped amenity list (including what the place does NOT have), host profile and stats, house rules, cancellation policy, sleeping arrangements, photo tour and the RATING BREAKDOWN. Carries NO nightly price - prices are search-only. Costs 1 credit.\",\n z.object({\n listing_id: str(\"Airbnb listing id or a full /rooms/ URL (1-500 characters); query params are discarded, since they carry someone else's dates.\"),\n check_in: ostr(\"Check-in date, YYYY-MM-DD. Must be sent with check_out. Does not produce a price: the room page has no nightly rate.\"),\n check_out: ostr(\"Check-out date, YYYY-MM-DD. Must be later than check_in and sent together with it.\"),\n adults: onum(\"Adult guests, >= 1.\"),\n children: onum(\"Children aged 2-12, >= 0.\"),\n infants: onum(\"Infants under 2, >= 0.\"),\n pets: onum(\"Pets, >= 0.\"),\n currency: ostr(\"ISO 4217 currency, 3 letters (default 'USD').\"),\n }),\n (i) => client.airbnb.listing(i as SdkOpts<typeof client.airbnb.listing>)\n ),\n tool(\n \"AIRBNB_REVIEWS\",\n \"Scavio Airbnb Reviews\",\n \"Airbnb review BODIES with per-review rating, date and reviewer name/photo/location, limit/offset paged at up to 50 per call. `count` is the listing's TOTAL review count, `returned` is how many this page holds. The rating breakdown lives on listing(), not here. Costs 1 credit.\",\n z.object({\n listing_id: str(\"Airbnb listing id or a full /rooms/ URL (1-500 characters).\"),\n currency: ostr(\"ISO 4217 currency, 3 letters (default 'USD').\"),\n limit: onum(\"Reviews to return, 1-50 (default 30). Upstream returns a fixed 7 when no explicit limit is sent.\"),\n offset: onum(\"Reviews to skip before this page, >= 0 (default 0).\"),\n }),\n (i) => client.airbnb.reviews(i as SdkOpts<typeof client.airbnb.reviews>)\n )\n );\n }\n\n // Glassdoor is keyed by employer_id: resolve a name with GLASSDOOR_COMPANIES first.\n if (all || enableGlassdoor) {\n tools.push(\n tool(\n \"GLASSDOOR_COMPANIES\",\n \"Scavio Glassdoor Companies\",\n \"START HERE. Resolve a company NAME to the employer_id every other Glassdoor method is keyed by, ranked by Glassdoor and de-duplicated. Costs 1 credit.\",\n z.object({\n query: str(\"Company name to resolve (1-120 characters).\"),\n }),\n (i) => client.glassdoor.companies(i as SdkOpts<typeof client.glassdoor.companies>)\n ),\n tool(\n \"GLASSDOOR_COMPANY\",\n \"Scavio Glassdoor Company\",\n \"Glassdoor employer profile: description, mission, industry, sector, HQ, size and revenue bands, stock symbol, year founded, overall and per-category ratings, star distribution, CEO approval, awards, FAQ and the five server-rendered reviews. Also returns reviews_url and salaries_url, which reviews() and salaries() accept as url to save a fetch. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters) in any form Glassdoor writes it: '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: the profile resolves on employer_id alone, it is ignored entirely when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters): /Overview/, /Reviews/ or /Salary/. A non-glassdoor.com host is rejected.\"),\n }),\n (i) => client.glassdoor.company(i as SdkOpts<typeof client.glassdoor.company>)\n ),\n tool(\n \"GLASSDOOR_REVIEWS\",\n \"Scavio Glassdoor Reviews\",\n \"Up to THREE full Glassdoor reviews - the cap is Glassdoor's login wall - with per-axis scores, pros, cons, advice, job title, location, employment status and employer response, plus complete rating statistics, star distribution, aggregate pro/con highlight terms and per-job-title review counts. There is no page param: move the window with category and employment_status. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters): '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected. Addressing by id costs two upstream fetches; the customer price is unchanged.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: ignored when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters). Pass back reviews_url from company() to skip the resolve fetch. A non-glassdoor.com host is rejected.\"),\n category: ostr(\"Restrict to reviews Glassdoor files under one topic. Closed enum: Glassdoor IGNORES an unknown value and serves the unfiltered set under a 200. Read filtered_review_count on the response to see how many match. Accepted values: 'career_development', 'compensation', 'culture', 'diversity_and_inclusion', 'management', 'work_life_balance'.\"),\n employment_status: ostr(\"Restrict to one kind of employment. Closed enum for the same reason as category; FREELANCE is deliberately absent because it was never confirmed to change the result set. Accepted values: 'full_time', 'part_time', 'contract', 'intern'.\"),\n }),\n (i) => client.glassdoor.reviews(i as SdkOpts<typeof client.glassdoor.reviews>)\n ),\n tool(\n \"GLASSDOOR_SALARIES\",\n \"Scavio Glassdoor Salaries\",\n \"Glassdoor salaries by job title, 10 titles per page: base-pay and total-pay percentiles P10-P90 with medians called out, sample counts, currency, pay period and last-reported date. The figures are Glassdoor's ESTIMATES for the title, not individual reported salaries. Provide employer_id or url. Costs 1 credit.\",\n z.object({\n employer_id: ostr(\"Glassdoor employer id (1-50 characters): '1699', 'E1699' or 'IE1699'. Must be a STRING - a JSON number is rejected. Addressing by id costs two upstream fetches; the customer price is unchanged.\"),\n company: ostr(\"Employer name as it appears in a Glassdoor slug (1-200 characters). COSMETIC: ignored when url is set, and it does not satisfy the employer_id-or-url requirement.\"),\n url: ostr(\"Any glassdoor.com employer URL (1-500 characters). Pass back salaries_url from company() to skip the resolve fetch. A non-glassdoor.com host is rejected.\"),\n page: onum(\"Results page, 1-based. Ten job titles per page; page_count on the response is how many pages exist.\"),\n }),\n (i) => client.glassdoor.salaries(i as SdkOpts<typeof client.glassdoor.salaries>)\n )\n );\n }\n\n if (all || enableYelp) {\n tools.push(\n tool(\n \"YELP_SEARCH\",\n \"Scavio Yelp Search\",\n \"Businesses in Yelp's ranked order: rating, review count, price band, categories, address, contact rails, hours, photos and a review snippet; every row carries both business_id and alias. Yelp fixes the page size at 10. Provide term and location, or url. Costs 2 credits.\",\n z.object({\n term: ostr(\"What to look for (1-200 characters): a category ('plumbers'), a dish, or a business name. Required together with location unless url is given.\"),\n location: ostr(\"Where to look (1-200 characters): city and region, a full address, or a postcode. Effectively required - Yelp geolocates a location-less search off the proxy exit, so the same request answers about a different metro run to run.\"),\n page: onum(\"Results page, 1-based. Yelp fixes the page size at 10.\"),\n sort: ostr(\"Result ordering (upstream default 'recommended'). Closed enum: Yelp IGNORES an unrecognised sortby and serves default ranking under a 200, billing a premium scrape for a sort that never ran. Accepted values: 'recommended', 'rating', 'review_count'.\"),\n price: oarrnum(\"Price bands to include, 1 ($) to 4 ($$$$); 1-4 values, combined freely - [1, 2] means $ or $$. Accepted values: 1, 2, 3, 4.\"),\n open_now: obool(\"Only businesses open at the moment of the request.\"),\n attributes: oarrstr(\"Raw Yelp filter aliases, max 20, each 1-100 characters ('RestaurantsDelivery', 'GoodForKids', 'WheelchairAccessible'). A deliberate PASSTHROUGH, not an enum - Yelp's vocabulary runs to ~117 values per vertical and an alias it does not know is ignored upstream, returning unfiltered results.\"),\n url: ostr(\"A full yelp.com/search URL (1-1000 characters) as an alternative to term + location; the query, offset and sort are read out of it and the URL is rebuilt.\"),\n }),\n (i) => client.yelp.search(i as SdkOpts<typeof client.yelp.search>)\n ),\n tool(\n \"YELP_BUSINESS\",\n \"Scavio Yelp Business\",\n \"One business in full: rating and per-star histogram, review count, price band, categories, address and coordinates, phone, website and menu links, hours and holidays, amenities, photos and videos, popular items, health inspections, Q&A, licences and claim status - plus the first page of reviews at no extra cost. Provide business_id or url. Costs 2 credits.\",\n z.object({\n business_id: ostr(\"A Yelp business alias ('desnudo-coffee-austin-2'), its opaque encid, or any yelp.com/biz URL carrying one (1-500 characters). Search rows return both id forms.\"),\n url: ostr(\"A full yelp.com/biz URL (1-1000 characters) as an alternative to business_id.\"),\n }),\n (i) => client.yelp.business(i as SdkOpts<typeof client.yelp.business>)\n ),\n tool(\n \"YELP_REVIEWS\",\n \"Scavio Yelp Reviews\",\n \"A page of reviews: rating, full text, language, author profile and expertise counts, attached photos, reaction counts and owner response. 10 per page. PAGE 1 IS REDUNDANT - it re-fetches the document business() already returned - so start at page 2. Provide business_id or url. Costs 2 credits.\",\n z.object({\n business_id: ostr(\"A Yelp business alias ('desnudo-coffee-austin-2'), its opaque encid, or any yelp.com/biz URL carrying one (1-500 characters).\"),\n url: ostr(\"A full yelp.com/biz URL (1-1000 characters) as an alternative to business_id.\"),\n page: onum(\"Reviews page, 1-based, 10 per page. Page 1 duplicates the reviews business() already returned and costs another 2 credits - start at 2. A page past the last review is a 404, not an empty result.\"),\n sort: ostr(\"Review ordering (upstream default 'relevance'). Closed enum: Yelp IGNORES an unrecognised value and serves default ranking under a billed 200. Accepted values: 'relevance', 'newest', 'oldest', 'rating_high', 'rating_low', 'elites'.\"),\n rating: onum(\"Only reviews at this star rating, 1-5. Changes filtered_review_count on the response, not review_count. Accepted values: 1, 2, 3, 4, 5.\"),\n }),\n (i) => client.yelp.reviews(i as SdkOpts<typeof client.yelp.reviews>)\n )\n );\n }\n\n if (all || enableAppStore) {\n tools.push(\n tool(\n \"APP_STORE_SEARCH\",\n \"Scavio App Store Search\",\n \"Search the App Store and get up to 200 fully-shaped app rows - the same 43-field row as app() - so a search doubles as a bulk metadata fetch and as a publisher lookup. NO PAGINATION: raise limit, there is no second page. Costs 1 credit.\",\n z.object({\n term: str(\"What to search for (1-500 characters). Apple matches an app name, a keyword OR a publisher name, so searching a developer returns their catalogue.\"),\n limit: onum(\"Apps to return, 1-200 (default 25). The ONLY lever on result volume: the search API has no pagination and every offset spelling is silently ignored.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'); decides price, currency, localised title and whether the app is sold there at all. Anything that is not exactly two letters is rejected with a free 400.\"),\n entity: ostr(\"Which catalogue to search: iPhone/iPad apps ('software', the default), iPad apps, or Mac App Store apps. These are separate stores, not a filter - Mac rows carry no iPad/Apple TV screenshots, advisories, features, supported devices or Game Center flag, returning them empty rather than absent. Accepted values: 'software', 'ipad_software', 'mac_software'.\"),\n lang: ostr(\"Listing text language as a five-letter code ('en_us', 'ja_jp'); any other shape is rejected. Independent of country: the storefront sets the price, this sets the words.\"),\n }),\n (i) => client.appStore.search(i as SdkOpts<typeof client.appStore.search>)\n ),\n tool(\n \"APP_STORE_APP\",\n \"Scavio App Store App\",\n \"Full App Store listing: title, description, developer and seller identity, price and currency, all-time and current-version ratings, version and release notes, genres, content rating and advisories, icons at three sizes, screenshots, download size, minimum OS, languages, supported devices and the Game Center and VPP flags. Costs 1 credit.\",\n z.object({\n app_id: str(\"App Store id - the digits after 'id' in an apps.apple.com URL - or the app's bundle id ('notion.id', 'com.burbn.instagram'); both resolve to the identical payload. 1-255 characters matching ^[A-Za-z0-9][A-Za-z0-9._-]*$, so a pasted apps.apple.com URL is rejected with a free 400. An id Apple cannot resolve is a billed 404.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'); decides price, currency, localised title and whether the app is sold there at all. Anything that is not exactly two letters is rejected with a free 400.\"),\n }),\n (i) => client.appStore.app(i as SdkOpts<typeof client.appStore.app>)\n ),\n tool(\n \"APP_STORE_REVIEWS\",\n \"Scavio App Store Reviews\",\n \"A page of App Store reviews: star rating, title, full text, author and the APP VERSION the review was written against. 50 per page, hard-stopped at page 10 - 500 reviews per storefront is Apple's anonymous ceiling. This endpoint cannot 404: an unknown id and a real app with no reviews return the same empty feed. Costs 1 credit.\",\n z.object({\n app_id: str(\"App Store id, NUMERIC ONLY - unlike app(), the reviews feed has no bundle-id form.\"),\n country: ostr(\"Two-letter ISO storefront code (default 'us'). Anything that is not exactly two letters is rejected with a free 400. Ask a different country to reach past the 500-review ceiling.\"),\n page: onum(\"Reviews page, 1-10, 50 reviews each (default 1). Apple hard-stops at page 10.\"),\n sort: ostr(\"Review ordering (default 'most_recent'). The choice decides whether the vote fields mean anything: under most_recent almost every review is too new to have been voted on and returns zeroes, while most_helpful returns them densely populated.\"),\n }),\n (i) => client.appStore.reviews(i as SdkOpts<typeof client.appStore.reviews>)\n )\n );\n }\n\n if (all || enableGooglePlay) {\n tools.push(\n tool(\n \"GOOGLE_PLAY_SEARCH\",\n \"Scavio Google Play Search\",\n \"Ranked Google Play apps: package name, title, developer, rating, install count, price and IAP range, content rating, icon and screenshots. A branded query returns the hero card as result 1 in the same row shape, plus Play's related-query rail. NO PAGINATION - one shelf of about 30 apps. Costs 2 credits.\",\n z.object({\n query: str(\"What to search the store for (1-200 characters): an app name, a publisher, or a category phrase. Apps only - games are folded into the apps vertical, but books and films use a different card shape and are not covered.\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings: at hl=pt-BR the title, description, install formatting and content rating all move with it. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.search(i as SdkOpts<typeof client.googlePlay.search>)\n ),\n tool(\n \"GOOGLE_PLAY_APP\",\n \"Scavio Google Play App\",\n \"Full Google Play store listing: installs including the REAL count Play publishes but never renders, rating and star histogram, description, developer identity and legal contact, price and IAPs, categories and gameplay tags, screenshots and trailer, version and Android requirement, release and update dates, changelog, the full permission tree, the Data safety table, the 20 server-rendered reviews and the similar-apps and more-by-developer rails. Costs 2 credits.\",\n z.object({\n app_id: str(\"Android package name ('com.spotify.music') or any play.google.com URL carrying one in its id param (1-500 characters).\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings: title, description, install formatting and content rating all move with it. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.app(i as SdkOpts<typeof client.googlePlay.app>)\n ),\n tool(\n \"GOOGLE_PLAY_REVIEWS\",\n \"Scavio Google Play Reviews\",\n \"A page of Google Play reviews: star score, full text, author, thumbs-up count, developer reply and the APP VERSION the reviewer was running. Paged by cursor, up to 200 per call. app() already returns the 20 reviews Play server-renders; use this to page past them or sort differently. Costs 2 credits.\",\n z.object({\n app_id: str(\"Android package name ('com.spotify.music') or any play.google.com URL carrying one in its id param (1-500 characters).\"),\n sort: ostr(\"Review ordering (default 'newest'). Closed enum. The cursor encodes the sort, so keep this identical when paging. Accepted values: 'relevance', 'newest', 'rating'.\"),\n count: onum(\"Reviews to return, 1-200 (default 50); 200 is our cap, not Play's. Play honours more, but a single page that large is megabytes for one credit - page with cursor instead.\"),\n cursor: ostr(\"Continuation token from a prior response's next_cursor (1-4000 characters). Opaque and SINGLE-USE, and it encodes the sort as well as the position - send it back with the SAME sort it came from. A cursor past the last review is a 404, not an empty page.\"),\n hl: ostr(\"UI language, 2-20 characters (default 'en'). Changes the STOREFRONT, not only the strings. Play silently falls back to English on a value it does not serve.\"),\n gl: ostr(\"Country code, 2-10 characters (default 'us'), deciding which storefront's price and availability are returned. Play silently falls back to the US storefront on a country it does not serve.\"),\n }),\n (i) => client.googlePlay.reviews(i as SdkOpts<typeof client.googlePlay.reviews>)\n )\n );\n }\n\n // SEC EDGAR is keyed by CIK: resolve a ticker with SEC_LOOKUP first.\n if (all || enableSec) {\n tools.push(\n tool(\n \"SEC_LOOKUP\",\n \"Scavio SEC Lookup\",\n \"START HERE. Resolve a company name or ticker (AAPL) to the CIK (0000320193) every other SEC EDGAR endpoint is keyed by. Up to 100 rows, tiered by match quality. Costs 1 credit.\",\n z.object({\n query: str(\"Ticker ('AAPL', 'BRK.B'), company name, or a fragment of one (1-200 characters); each row carries its match tier as 'match'.\"),\n limit: onum(\"Rows to return, 1-100. Defaults to 10. Sizes the response; it is not a page param.\"),\n exchange: ostr(\"Restrict to one listing venue; matched case-insensitively, so 'Nasdaq' also works. Filers the SEC lists with no exchange at all are excluded by any value. Accepted values: 'NASDAQ', 'NYSE', 'OTC', 'CBOE'.\"),\n }),\n (i) => client.sec.lookup(i as SdkOpts<typeof client.sec.lookup>)\n ),\n tool(\n \"SEC_COMPANY\",\n \"Scavio SEC Company\",\n \"SEC filer profile: legal and former names, SIC industry, filer category, EIN, LEI, state of incorporation, fiscal year end, addresses, every ticker with its exchange, and a preview of its 10 most recent filings. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK in any spelling (1-20 characters): 320193, 0000320193 or CIK0000320193. A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), dotted or dashed (BRK.B / BRK-B). Wins over cik when both are given.\"),\n }),\n (i) => client.sec.company(i as SdkOpts<typeof client.sec.company>)\n ),\n tool(\n \"SEC_FILINGS\",\n \"Scavio SEC Filings\",\n \"A page of one filer's filings: accession number, form and root form, filing and period dates, 8-K item codes, direct links to the primary document, filing index and attachment directory. Up to 500 per page. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n form: ostrarr(\"Form types to keep: '10-K', ['10-K', '10-Q'] or the comma-joined '10-K,8-K'; each value 1-50 characters, at most 25 values. Matched against the form AND its root form, so 10-K also returns 10-K/A amendments; ask for '10-K/A' to get only amendments.\"),\n date_from: ostr(\"Earliest filing date, inclusive (YYYY-MM-DD).\"),\n date_to: ostr(\"Latest filing date, inclusive (YYYY-MM-DD).\"),\n page: onum(\"Results page, 1-based; page size is whatever limit is set to. No upper bound.\"),\n limit: onum(\"Filings per page, 1-500. Defaults to 50.\"),\n include_history: obool(\"Also fetch the archived filing history beyond EDGAR's 'recent' block, which is not a fixed window (a decade for a quiet filer, about a year for a prolific one). Off by default; at most 10 archived shards are fetched, history_truncated says when a filer had more, and it is still 1 credit.\"),\n }),\n (i) => client.sec.filings(i as SdkOpts<typeof client.sec.filings>)\n ),\n tool(\n \"SEC_CONCEPT\",\n \"Scavio SEC Concept\",\n \"Every value a filer reported for one XBRL concept, newest period first, with the form and filing each number came from. Restatements are kept, not collapsed. Up to 2000 rows. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n concept: str(\"XBRL concept tag, CASE-SENSITIVE (1-120 characters, ^[A-Za-z][A-Za-z0-9]*$): 'NetIncomeLoss' matches, 'netincomeloss' is a 404 upstream. Use facts() to list what a filer actually reports.\"),\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n taxonomy: ostr(\"Reporting taxonomy (1-40 characters, ^[A-Za-z][A-Za-z0-9-]*$): us-gaap, dei, ifrs-full or srt. Defaults to 'us-gaap'.\"),\n unit: ostr(\"Unit of measure to keep (1-40 characters), e.g. 'USD' vs 'USD/shares'.\"),\n form: ostr(\"Form to keep (1-50 characters). EXACT match here, unlike filings(), so '10-K' excludes 10-K/A.\"),\n limit: onum(\"Rows to return, 1-2000. Defaults to 250. Sizes the response; it is not a page param.\"),\n }),\n (i) => client.sec.concept(i as SdkOpts<typeof client.sec.concept>)\n ),\n tool(\n \"SEC_FACTS\",\n \"Scavio SEC Facts\",\n \"The index of every XBRL concept a filer reports - tag, label, description, units and most recent value - across us-gaap, dei and any other taxonomy it uses. This is how you find what to ask concept() for. Up to 2000 rows. Provide cik or ticker. Costs 1 credit.\",\n z.object({\n cik: ostr(\"Filer CIK, zero-padded or bare (1-20 characters). A ticker is accepted here too.\"),\n ticker: ostr(\"Ticker symbol (1-20 characters), as an alternative to cik.\"),\n taxonomy: ostr(\"Restrict to one taxonomy (1-40 characters), e.g. 'us-gaap' or 'dei'.\"),\n query: ostr(\"Case-insensitive substring matched against the tag name and label (1-200 characters).\"),\n limit: onum(\"Rows to return, 1-2000. Defaults to 250. Sizes the response; it is not a page param.\"),\n }),\n (i) => client.sec.facts(i as SdkOpts<typeof client.sec.facts>)\n ),\n tool(\n \"SEC_SEARCH\",\n \"Scavio SEC Search\",\n \"EDGAR full-text search, coverage starting 2001: each hit is the matching DOCUMENT with its URL, form, filing date and filer identity, plus facets by company, form, industry and state. 100 documents per page, last page is 100. Costs 1 credit.\",\n z.object({\n query: ostr(\"Full-text query over filing documents (1-500 characters); a quoted phrase is matched exactly, bare words as a bag of terms. Optional - a cik, ticker, form or date filter on its own is a valid search.\"),\n cik: ostrarr(\"Restrict to one or more filers by CIK: a single value, a list, or a comma-joined string; each 1-20 characters, at most 25 values. Tickers are accepted here too.\"),\n ticker: ostrarr(\"Restrict to one or more filers by ticker symbol: a single value, a list, or a comma-joined string; each 1-20 characters, at most 25 values.\"),\n form: ostrarr(\"Form types to keep: '8-K', ['10-K', '10-Q'] or the comma-joined '10-K,10-Q'; each 1-50 characters, at most 25 values.\"),\n date_from: ostr(\"Earliest filing date, inclusive (YYYY-MM-DD). Full-text coverage starts in 2001.\"),\n date_to: ostr(\"Latest filing date, inclusive (YYYY-MM-DD).\"),\n location: ostrarr(\"Filer business-address locations as EDGAR's own 2-character codes (CA, NY, and its alphanumeric codes for foreign jurisdictions): a single value, a list, or a comma-joined string; at most 25 values.\"),\n sort: ostr(\"Result ordering. Defaults to the index's own relevance ranking. Accepted values: 'relevance', 'newest', 'oldest'.\"),\n page: onum(\"Results page, 1-based, 1-100, 100 documents per page. The SEC's index refuses a result window past 10,000, so 100 is the last page for any query.\"),\n }),\n (i) => client.sec.search(i as SdkOpts<typeof client.sec.search>)\n )\n );\n }\n\n if (all || enableRedfin) {\n tools.push(\n tool(\n \"REDFIN_SEARCH\",\n \"Scavio Redfin Search\",\n \"Redfin listings: price, price per sqft, beds, baths, living area, lot size, year built, coordinates, listing remarks and full photo galleries, for sale, sold or for rent. Up to 350 per page. Provide location, or region_id together with region_type. Costs 1 credit.\",\n z.object({\n location: ostr(\"A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or a bare 5-digit ZIP (1-500 characters). CITY NAMES ARE NOT ACCEPTED - Redfin's own name lookup is blocked to us; use region_id + region_type instead.\"),\n region_id: onum(\"Redfin internal region id (>= 1), used together with region_type. NOT a ZIP code - the two are different number spaces and a ZIP here resolves to another city rather than failing.\"),\n region_type: onum(\"Region kind that region_id belongs to: 1 neighborhood, 2 ZIP, 5 county, 6 city. Must be sent together with region_id or both are ignored in favour of location.\"),\n listing_status: ostr(\"Market to search. Defaults to 'for_sale'. Accepted values: 'for_sale', 'sold', 'for_rent'.\"),\n sold_within_days: onum(\"Sold within the last N days (>= 1). REJECTED unless listing_status='sold', where it defaults to 90.\"),\n page: onum(\"Results page, 1-based; page size is whatever limit is set to. No upper bound.\"),\n limit: onum(\"Listings per page, 1-350. Defaults to 100.\"),\n sort: ostr(\"Result sort order. Defaults to 'recommended', Redfin's own ranking. Accepted values: 'recommended', 'price_low', 'price_high', 'newest', 'oldest', 'sqft_low', 'sqft_high', 'price_per_sqft_low', 'price_per_sqft_high'.\"),\n min_price: onum(\"Minimum price, inclusive (>= 0). Monthly rent when listing_status='for_rent'.\"),\n max_price: onum(\"Maximum price, inclusive (>= 0). Monthly rent when listing_status='for_rent'.\"),\n beds_min: onum(\"Minimum bedrooms (whole number >= 0); fractional values are rejected.\"),\n beds_max: onum(\"Maximum bedrooms (whole number >= 0); fractional values are rejected.\"),\n baths_min: onum(\"Minimum bathrooms (whole number >= 0). WHOLE BATHS ONLY - 1.5 is rejected rather than silently truncated to 1. There is no baths_max.\"),\n sqft_min: onum(\"Minimum living area in square feet (whole number >= 0).\"),\n sqft_max: onum(\"Maximum living area in square feet (whole number >= 0).\"),\n lot_size_min: onum(\"Minimum lot size in square feet (whole number >= 0). There is no lot_size_max.\"),\n year_built_min: onum(\"Earliest year built (whole number >= 0).\"),\n year_built_max: onum(\"Latest year built (whole number >= 0).\"),\n max_hoa: onum(\"Maximum monthly HOA fee in dollars (>= 0).\"),\n property_type: ostr(\"Restrict to one property type. Accepted values: 'house', 'condo', 'townhouse', 'multi_family', 'land', 'other', 'co_op'.\"),\n has_pool: obool(\"Only listings with a pool.\"),\n max_days_on_market: onum(\"Listed at most N days ago (whole number >= 0). Cannot be combined with min_days_on_market - Redfin expresses both bounds through one param.\"),\n min_days_on_market: onum(\"Listed at least N days ago (whole number >= 0). Cannot be combined with max_days_on_market.\"),\n }),\n (i) => client.redfin.search(i as SdkOpts<typeof client.redfin.search>)\n ),\n tool(\n \"REDFIN_PROPERTY\",\n \"Scavio Redfin Property\",\n \"One Redfin listing in full: price, Redfin Estimate and rental estimate, complete MLS fact sheet, price and tax history, listing agents, open houses, schools, climate risk, walkability, sun exposure, monthly weather, permits, zoning, comparable sales and photos. Costs 1 credit.\",\n z.object({\n property_id: str(\"Redfin property id, or any redfin.com listing URL carrying one (1-500 characters).\"),\n }),\n (i) => client.redfin.property(i as SdkOpts<typeof client.redfin.property>)\n ),\n tool(\n \"REDFIN_MARKET\",\n \"Scavio Redfin Market\",\n \"Redfin housing-market stats for a region: median list and sale price, price per sqft, sale-to-list ratio, average offers and days on market, YoY movement, 0-100 compete score, live inventory by property type and by bedroom count, and Redfin agent presence. Provide location, or region_id together with region_type. Costs 1 credit.\",\n z.object({\n location: ostr(\"A redfin.com region URL (/city/, /neighborhood/, /county/, /zipcode/) or a bare 5-digit ZIP (1-500 characters). City names are not accepted.\"),\n region_id: onum(\"Redfin internal region id (>= 1), used together with region_type. Not a ZIP code.\"),\n region_type: onum(\"Region kind that region_id belongs to: 1 neighborhood, 2 ZIP, 5 county, 6 city. Must be sent together with region_id or both are ignored in favour of location.\"),\n }),\n (i) => client.redfin.market(i as SdkOpts<typeof client.redfin.market>)\n )\n );\n }\n\n if (all || enableCompaniesHouse) {\n tools.push(\n tool(\n \"COMPANIES_HOUSE_SEARCH\",\n \"Scavio Companies House Search\",\n \"START HERE. Search the UK register by name and get the company_number every other Companies House endpoint is keyed by, plus status, incorporation or dissolution date, registered office and matched former names. 20 per page, last page is 50. Costs 1 credit.\",\n z.object({\n query: str(\"Company name or fragment (1-200 characters, non-blank). Matches CURRENT AND FORMER names.\"),\n page: onum(\"Results page, 1-based, 1-50, 20 results per page. Defaults to 1. The register serves only a 1000-result window per term whatever hit count it prints, and answers page 51 with HTTP 416.\"),\n }),\n (i) => client.companiesHouse.search(i as SdkOpts<typeof client.companiesHouse.search>)\n ),\n tool(\n \"COMPANIES_HOUSE_COMPANY\",\n \"Scavio Companies House Company\",\n \"Full UK register entry: status, type, incorporation and dissolution dates, registered office, SIC codes, previous names, accounts and confirmation-statement due dates with overdue flags, and whether it has charges, insolvency history, officers or UK establishments. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you, so '445790' and 'sc090312' both work. Registry prefixes supported: SC, NI, OC, SO, NC, FC, BR, CE.\"),\n }),\n (i) => client.companiesHouse.company(i as SdkOpts<typeof client.companiesHouse.company>)\n ),\n tool(\n \"COMPANIES_HOUSE_OFFICERS\",\n \"Scavio Companies House Officers\",\n \"UK company officers, current and resigned, 35 per page: name, role, appointment and resignation dates, correspondence address, nationality, country of residence, month-and-year date of birth and identity-verification status. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you.\"),\n page: onum(\"Results page, 1-based, 35 per page. Defaults to 1. No upper bound: past the last page the register answers an ordinary 200 with an empty list, identical to a company with no officers.\"),\n }),\n (i) => client.companiesHouse.officers(i as SdkOpts<typeof client.companiesHouse.officers>)\n ),\n tool(\n \"COMPANIES_HOUSE_FILING_HISTORY\",\n \"Scavio Companies House Filing History\",\n \"UK filings, most recent first: date, filing type code (AA, CS01, SH03), description, register annotations and child documents, and a link to the filed PDF with its page count. A filing the register has not finished processing carries a processing_note instead of a document. Costs 1 credit.\",\n z.object({\n company_number: str(\"UK company number (1-20 characters), zero-padded and upper-cased for you.\"),\n page: onum(\"Results page, 1-based. Defaults to 1. No upper bound: past the last page the register answers an ordinary 200 with an empty list.\"),\n }),\n (i) => client.companiesHouse.filingHistory(i as SdkOpts<typeof client.companiesHouse.filingHistory>)\n )\n );\n }\n\n if (all || enableG2) {\n tools.push(\n tool(\n \"G2_SEARCH\",\n \"Scavio G2 Search\",\n \"Search G2, the B2B software review site, for products: star rating, review count, vendor, categories, seller description and logo, with product_id and slug on every row. Up to 100 results per page (server default 20) and page-paginated; total_results is G2's Products-tab headline and caps at 10000, while total_by_type splits the query across products, sellers, categories and discussions. Provide query or url. Costs 5 credits.\",\n z.object({\n query: ostr(\"Search term (1-200 characters). Provide this or url.\"),\n page: onum(\"1-based page number; page size follows limit (server default 20). G2 keeps paginating well past its own widget's page links.\"),\n limit: onum(\"Results per page (1-100; server default 20). The 100 ceiling is ours, to keep a single request inside the 60s deadline; G2 itself paginates at any size.\"),\n sort: ostr(\"Result sort order (server default 'relevance'). Closed enum: G2 silently accepts an unknown sort and answers 200 with an unstated ordering. Accepted values: 'relevance', 'popular', 'alphabetical', 'rating'.\"),\n rating: onum(\"Only products at or above this star rating (1-5, sent as an integer). Omit for no rating floor. Accepted values: 1, 2, 3, 4, 5.\"),\n url: ostr(\"Full g2.com/search URL, as an alternative to query (1-1000 characters; the host is checked by the transport).\"),\n }),\n (i) => client.g2.search(i as SdkOpts<typeof client.g2.search>)\n ),\n tool(\n \"G2_PRODUCT\",\n \"Scavio G2 Product\",\n \"Full G2 product profile: rating with per-star histogram, review count, vendor, description and seller website, pricing editions with parsed amounts, feature groups, categories and breadcrumbs, supported languages, integrations, alternatives, head-to-head comparisons, media, community discussions and G2's AI-derived pros and cons. Carries NO review text at all -- G2 loads review bodies in a separate frame, so call reviews() for those. Provide product_id or url. Costs 5 credits.\",\n z.object({\n product_id: ostr(\"G2 product slug ('notion') or the numeric G2 id ('82623') as a string (1-200 characters); both resolve on the same upstream path.\"),\n url: ostr(\"Full g2.com product URL, as an alternative to product_id (1-1000 characters).\"),\n }),\n (i) => client.g2.product(i as SdkOpts<typeof client.g2.product>)\n ),\n tool(\n \"G2_REVIEWS\",\n \"Scavio G2 Reviews\",\n \"A page of G2 reviews: rating, title, likes and dislikes, problems solved, reviewer job title, industry and company size, validated and incentivized flags -- plus what the profile page has no form of: exact per-star counts, pros and cons with per-theme counts, and company-size, role, industry, region and category facets with counts. Fixed at 10 reviews per page and paginates well past the 10 pages G2's own widget links to. Provide product_id or url. Costs 5 credits.\",\n z.object({\n product_id: ostr(\"G2 product slug or numeric G2 id as a string (1-200 characters).\"),\n url: ostr(\"Full g2.com reviews URL, as an alternative to product_id (1-1000 characters).\"),\n page: onum(\"1-based page number; fixed at 10 reviews per page.\"),\n sort: ostr(\"Review sort order (server default 'relevance'). Closed enum: an unknown sort is silently accepted upstream and never runs. Accepted values: 'relevance', 'newest', 'most_helpful', 'rating_high', 'rating_low'.\"),\n rating: onum(\"Only reviews in this star bucket (1-5, sent as an integer). Buckets are half- star-inclusive: 1 returns 0, 0.5 and 1-star reviews. Accepted values: 1, 2, 3, 4, 5.\"),\n company_size: ostr(\"Reviewer company size: small_business is 50 employees or fewer, mid_market 51-1000, enterprise over 1000. Closed enum -- an unknown value matches nothing and returns a billed 'Reviews (0)'.\"),\n role: ostr(\"Reviewer role. Closed enum -- an unknown value matches nothing rather than erroring. Accepted values: 'user', 'administrator', 'executive_sponsor', 'internal_consultant', 'consultant', 'agency', 'industry_analyst'.\"),\n region: ostr(\"Reviewer region. Closed enum -- an unknown value matches nothing rather than erroring. Accepted values: 'north_america', 'europe', 'asia', 'latin_america', 'anz', 'middle_east', 'africa'.\"),\n query: ostr(\"Full-text search within this product's reviews (1-200 characters); narrows the review list AND every facet count.\"),\n }),\n (i) => client.g2.reviews(i as SdkOpts<typeof client.g2.reviews>)\n )\n );\n }\n\n if (all || enableCapterra) {\n tools.push(\n tool(\n \"CAPTERRA_SEARCH\",\n \"Scavio Capterra Search\",\n \"Search Capterra, the B2B software review site: 20 ranked products with name, vendor description, rating, review count, logo and paid-placement flag, each row carrying product_id and slug. The result set is fixed at 20 and does NOT paginate -- Capterra serves identical rows for page 2, so there is deliberately no page parameter. Provide query or url. Costs 2 credits.\",\n z.object({\n query: ostr(\"Search term (1-200 characters). Required in practice: a term-less Capterra search serves a fixed popular-products list unrelated to the caller.\"),\n url: ostr(\"Full capterra.com search URL, as an alternative to query (1-1000 characters; the transport also accepts capterra.co.uk and capterra.com.br hosts).\"),\n }),\n (i) => client.capterra.search(i as SdkOpts<typeof client.capterra.search>)\n ),\n tool(\n \"CAPTERRA_PRODUCT\",\n \"Scavio Capterra Product\",\n \"Full Capterra profile: rating with per-star histogram and the four scored criteria, likelihood to recommend, review sentiment and topics, the complete pricing table with every plan and its features, every rated feature and integration, AI-derived pros and cons with the quoted review, FAQs, screenshots, badges and awards, competitor comparisons and alternatives, and the buyer profile by company size, industry and job function -- PLUS the 25 most recent reviews at no extra cost. vendor is always null here: Capterra does not publish it as structured data on the product page. Provide product_id or url. Costs 2 credits.\",\n z.object({\n product_id: ostr(\"The number in a Capterra product path such as /p/186596/Notion/ (1-50 characters). Must be a STRING -- a JSON number is rejected.\"),\n slug: ostr(\"Product slug (1-200 characters). Cosmetic on this endpoint -- a wrong slug still returns the right profile -- but load-bearing on reviews().\"),\n url: ostr(\"Full Capterra product URL, as an alternative to product_id (1-1000 characters).\"),\n }),\n (i) => client.capterra.product(i as SdkOpts<typeof client.capterra.product>)\n ),\n tool(\n \"CAPTERRA_REVIEWS\",\n \"Scavio Capterra Reviews\",\n \"A page of Capterra reviews: overall score plus five per-criterion scores, title, pros, cons, advice, usage duration, incentivized flag, alternatives considered and what they switched from, reviewer job title, industry and company size, and the vendor response -- plus a competitor list richer than the profile's, each alternative with its own rating histogram and starting price. 25 reviews per page, capped at page 100. Page 1 already rides along inside product(), so use this to page past it. Provide product_id or url. Costs 2 credits.\",\n z.object({\n product_id: ostr(\"Capterra product id as a string (1-50 characters).\"),\n slug: ostr(\"Product slug (1-200 characters). LOAD-BEARING here: it is case-sensitive upstream and a wrong one silently serves page one under a billed 200. Pass back the slug from search() or product().\"),\n url: ostr(\"Full Capterra reviews URL, as an alternative to product_id (1-1000 characters). Passing back reviews_url from product() is the reliable way to page.\"),\n page: onum(\"1-based page number (1-100); 25 reviews per page. 100 is a hard cap whatever the review count says -- past it Capterra answers 200 with page one.\"),\n }),\n (i) => client.capterra.reviews(i as SdkOpts<typeof client.capterra.reviews>)\n )\n );\n }\n\n // Google Ads Transparency is keyed by advertiser_id: resolve a brand with\n // GOOGLE_ADS_ADVERTISERS first.\n if (all || enableGoogleAds) {\n tools.push(\n tool(\n \"GOOGLE_ADS_ADVERTISERS\",\n \"Scavio Google Ads Advertisers\",\n \"Resolve a brand name or domain to the advertiser_id that search() and creative() are keyed by. Returns two row kinds in one list: 'advertiser' rows carrying the id, verified name, verification country and total ad count as a range, and 'domain' rows carrying a website. A name query returns both kinds; a domain-shaped query returns domains only. Autocomplete-backed, roughly 20 rows per arm, and it does not paginate. Costs 1 credit.\",\n z.object({\n query: str(\"Brand name or domain to resolve (1-200 characters).\"),\n region: ostr(\"ISO 3166-1 alpha-2 country ('US', 'GB', 'DE') or a Google geo criteria id as a string (2-12 characters). Default: no region filter.\"),\n limit: onum(\"Rows per arm (1-20; server default 10). Advertisers and domains are capped separately, so a name query can return up to twice this many rows.\"),\n }),\n (i) => client.googleAds.advertisers(i as SdkOpts<typeof client.googleAds.advertisers>)\n ),\n tool(\n \"GOOGLE_ADS_SEARCH\",\n \"Scavio Google Ads Search\",\n \"Every ad Google Ads Transparency holds for one advertiser: the creative (archived image, rich-media bundle, Google's renderer link, dimensions), advertiser id and name, format, first and last seen dates and days actually run, plus total_ads_min and total_ads_max -- Google publishes the advertiser's ad total as a range, never an exact figure. Up to 100 ads per page (server default 40); paginate by sending next_cursor back as cursor alongside the SAME filters. Provide domain or advertiser_id. Costs 1 credit.\",\n z.object({\n domain: ostr(\"Advertiser website (1-253 characters): bare host, www host or full URL, reduced to the registrable host. The only way to get `domain` back on each row.\"),\n advertiser_id: ostr(\"Google advertiser id, e.g. 'AR16735076323512287233' (3-40 characters). The shape is checked before any request, so a typo costs no credits. Querying by id drops `domain` from every row.\"),\n region: ostr(\"ISO 3166-1 alpha-2 country ('US', 'GB', 'DE') or a Google geo criteria id as a string (2-12 characters). Scopes the deep links on every row, and the same advertiser can share zero creatives between two countries. Default: worldwide.\"),\n format: ostr(\"Creative format. The three sets are disjoint -- an advertiser's text, image and video ads share no creatives. Default: all formats.\"),\n platform: ostr(\"Google surface the ad ran on. Default: all surfaces. Accepted values: 'play', 'maps', 'search', 'shopping', 'youtube'.\"),\n topic: ostr(\"Ad topic (server default 'all'). Accepted values: 'all', 'political'.\"),\n limit: onum(\"Ads per page (1-100; server default 40). 100 is a hard upstream ceiling, not our policy: Google answers a larger request with zero rows rather than an error.\"),\n cursor: ostr(\"next_cursor from the previous response (1-4000 characters), 100 ads per page. Re-send the same filters alongside it; next_cursor is null once exhausted.\"),\n }),\n (i) => client.googleAds.search(i as SdkOpts<typeof client.googleAds.search>)\n ),\n tool(\n \"GOOGLE_ADS_CREATIVE\",\n \"Scavio Google Ads Creative\",\n \"One creative in full, and the only endpoint carrying its history: every size variation of the asset, the impression bucket, the per-region breakdown with first and last shown dates and a per-surface impression split inside each region, the format, Google's category label and the funder disclosure on political ads. Impressions and first_shown are EEA-only (DSA-compelled) and come back null for US creatives, and an impression bucket may carry only a lower or only an upper bound. Costs 1 credit.\",\n z.object({\n advertiser_id: str(\"Google advertiser id, e.g. 'AR16735076323512287233' (3-40 characters).\"),\n creative_id: str(\"Creative id (3-40 characters). It must belong to the advertiser_id sent with it -- the lookup is keyed by the pair and a mismatched pair is a 404.\"),\n }),\n (i) => client.googleAds.creative(i as SdkOpts<typeof client.googleAds.creative>)\n )\n );\n }\n\n // Meta Ad Library is served from /api/v1/meta-ads/* - HYPHENATED. The path is\n // never derived from the namespace key.\n if (all || enableMetaAds) {\n tools.push(\n tool(\n \"META_ADS_SEARCH\",\n \"Scavio Meta Ads Search\",\n \"Search the Meta Ad Library by keyword: 30 ads on page 1 with the full creative -- page name, ad copy, headline, CTA, images and videos, the platforms each ran on and its run dates -- then 10 ads per cursor page, walking has_next_page to the end of the query. total_results caps at 50000 with total_is_capped true, because Meta only reports '>50,000'; never present it as an exact count. Every page costs 1 credit.\",\n z.object({\n query: str(\"Keyword to search the ad library for (1-200 characters).\"),\n country: ostr(\"Ad library country as an exactly 2-character ISO 3166-1 alpha-2 code (server default 'US').\"),\n active_status: ostr(\"Whether the ad is still running (server default 'all'). Accepted values: 'all', 'active', 'inactive'.\"),\n ad_type: ostr(\"Set 'political_and_issue_ads' to expose spend, reach, impressions and the paid-for-by disclosure; commercial ads leave all four null (server default 'all').\"),\n media_type: ostr(\"Creative media filter. Default: no media filter. Accepted values: 'all', 'image', 'video', 'meme', 'image_and_meme', 'none'.\"),\n search_type: ostr(\"How the query is matched (server default 'keyword_unordered'). Accepted values: 'keyword_unordered', 'keyword_exact_phrase'.\"),\n cursor: ostr(\"next_cursor from the previous response: page 1 is 30 ads, every cursor page is 10. The cursor is a self-contained blob, so ALL other filters are ignored when it is present.\"),\n }),\n (i) => client.metaAds.search(i as SdkOpts<typeof client.metaAds.search>)\n ),\n tool(\n \"META_ADS_ADVERTISER\",\n \"Scavio Meta Ads Advertiser\",\n \"Every ad a Facebook Page is running, by numeric page id: 30 ads on page 1 with the same creative detail as search(), then 10 ads per cursor page, walking has_next_page to the end of the advertiser. Every page costs 1 credit.\",\n z.object({\n page_id: str(\"The advertiser's numeric Facebook Page id (3-25 digits, as a string).\"),\n country: ostr(\"Ad library country as an exactly 2-character ISO 3166-1 alpha-2 code (server default 'US').\"),\n active_status: ostr(\"Whether the ad is still running (server default 'all'). Accepted values: 'all', 'active', 'inactive'.\"),\n ad_type: ostr(\"Set 'political_and_issue_ads' to expose spend, reach, impressions and the paid-for-by disclosure; commercial ads leave all four null (server default 'all').\"),\n media_type: ostr(\"Creative media filter. Default: no media filter. Accepted values: 'all', 'image', 'video', 'meme', 'image_and_meme', 'none'.\"),\n cursor: ostr(\"next_cursor from the previous response: page 1 is 30 ads, every cursor page is 10. ALL other filters are ignored when it is present.\"),\n }),\n (i) => client.metaAds.advertiser(i as SdkOpts<typeof client.metaAds.advertiser>)\n ),\n tool(\n \"META_ADS_AD\",\n \"Scavio Meta Ads Ad\",\n \"One Meta ad in full by archive id: creative, advertiser, run dates, the platforms it ran on, and the political disclosure when the ad carries one. Commercial ads leave spend, reach and impressions null. Costs 1 credit.\",\n z.object({\n ad_archive_id: str(\"Meta ad archive id (3-25 digits, as a string).\"),\n }),\n (i) => client.metaAds.ad(i as SdkOpts<typeof client.metaAds.ad>)\n )\n );\n }\n\n // extract is a CORE endpoint, not a platform: the top-level client.extract(),\n // never client.extract.extract(). It is the agent's 'read this page' primitive.\n if (all || enableExtract) {\n tools.push(\n tool(\n \"EXTRACT\",\n \"Scavio Extract\",\n \"Read any URL and get the page back as raw HTML, readability Markdown or plain text: { url, format, mode, content, content_length }. Tier-priced by mode: 'normal' and 'advanced' cost 1 credit, 'ultra' costs 2. Only a successful extraction is billed - a dead link, bot wall or timeout costs nothing.\",\n z.object({\n 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.\"),\n format: ostr(\"Output format: 'html' is the raw page, 'markdown' a readability extraction, 'text' that markdown flattened to plain text (server default 'markdown').\"),\n 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'.\"),\n }),\n (i) => client.extract(i as SdkOpts<typeof client.extract>)\n )\n );\n }\n\n // Website map, crawl and batch. Opt-in: a crawl bills per page.\n if (all || enableCrawl) {\n const crawlStatus: JobStatusFn = (id, q) => client.extract.crawlStatus(id, q);\n const batchStatus: JobStatusFn = (id, q) => client.extract.batchStatus(id, q);\n const readStatus =\n (status: JobStatusFn) =>\n async ({ id, limit, ...q }: z.infer<typeof JOB_STATUS_PARAMS>) =>\n (await status(id, {\n ...(q as JobQuery),\n limit: limit ?? JOB_RESULTS_DEFAULT_LIMIT,\n })) as Record<string, unknown>;\n tools.push(\n tool(\n \"MAP_WEBSITE\",\n \"Scavio Map Website\",\n \"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.\",\n z.object({\n url: str(\"The site to map. A bare host is upgraded to https.\"),\n search: ostr(\"Only return URLs containing every word of this text (case-insensitive).\"),\n 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).\"),\n sitemap: ostr(\"'include' combines the site's sitemaps with the start page's links (default); 'only' uses sitemaps alone; 'skip' uses page links alone.\"),\n include_subdomains: obool(\"Also return URLs on subdomains of the site (default false).\"),\n include_paths: oarrstr(\"Keep only URLs matching these. \" + JOB_PATHS),\n exclude_paths: oarrstr(\"Drop URLs matching these. \" + JOB_PATHS),\n ignore_query_parameters: obool(\"Treat URLs that differ only by query string as one URL (default true).\"),\n mode: JOB_MODE,\n }),\n async (i) =>\n (await client.extract.map(i as SdkOpts<typeof client.extract.map>)) as unknown as Record<string, unknown>\n ),\n tool(\n \"CRAWL_WEBSITE\",\n \"Scavio Crawl Website\",\n \"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,\n z.object({\n url: str(\"Where the crawl starts. Only pages on the same site are crawled.\"),\n 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.\"),\n max_depth: onum(\"How many links away from the start page to follow, 0-10 (default 3). 0 fetches only the start page.\"),\n include_paths: oarrstr(\"Crawl only paths matching these. \" + JOB_PATHS),\n exclude_paths: oarrstr(\"Skip paths matching these. \" + JOB_PATHS),\n allow_subdomains: obool(\"Also crawl subdomains of the site (default false).\"),\n ignore_query_parameters: obool(\"Treat URLs that differ only by query string as one page (default true).\"),\n sitemap: ostr(\"'include' also starts from the site's sitemap (default); 'skip' follows links only; 'only' fetches sitemap pages without following links.\"),\n format: JOB_FORMAT,\n mode: JOB_MODE,\n wait_seconds: JOB_WAIT,\n limit: JOB_LIMIT,\n include_content: JOB_INCLUDE_CONTENT,\n }),\n (i) =>\n startAndWait(\n (body) => client.extract.crawl(body as SdkOpts<typeof client.extract.crawl>),\n crawlStatus,\n i,\n pollIntervalMs\n )\n ),\n tool(\n \"CRAWL_STATUS\",\n \"Scavio Crawl Status\",\n \"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.\",\n JOB_STATUS_PARAMS,\n readStatus(crawlStatus)\n ),\n tool(\n \"BATCH_EXTRACT\",\n \"Scavio Batch Extract\",\n \"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,\n z.object({\n urls: arrstr(\"The pages to extract (duplicates removed). Plan limits: Free 10, PAYG 50, Project 100, Bootstrap 500, Startup and Growth 1,000.\"),\n format: JOB_FORMAT,\n mode: JOB_MODE,\n wait_seconds: JOB_WAIT,\n limit: JOB_LIMIT,\n include_content: JOB_INCLUDE_CONTENT,\n }),\n (i) =>\n startAndWait(\n (body) => client.extract.batch(body as SdkOpts<typeof client.extract.batch>),\n batchStatus,\n i,\n pollIntervalMs\n )\n ),\n tool(\n \"BATCH_STATUS\",\n \"Scavio Batch Status\",\n \"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.\",\n JOB_STATUS_PARAMS,\n readStatus(batchStatus)\n )\n );\n }\n\n return experimental_createToolkit(\"SCAVIO\", {\n name: \"Scavio\",\n description:\n \"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.\",\n tools,\n });\n}\n\nexport default buildScavioToolkit;\n"],"mappings":"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","names":[]}