one-search-mcp 1.0.9 → 1.0.10

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","../src/search/bing.ts","../src/search/duckduckgo.ts","../src/search/searxng.ts","../src/search/tavily.ts","../src/libs/browser/types.ts","../src/libs/browser/finder.ts","../src/libs/browser/base.ts","../src/libs/browser/local.ts","../src/libs/browser/remote.ts","../src/libs/browser-search/readability.ts","../src/libs/browser-search/search.ts","../src/libs/browser-search/utils.ts","../src/libs/browser-search/queue.ts","../src/libs/browser-search/engines/bing.ts","../src/libs/browser-search/engines/baidu.ts","../src/libs/browser-search/engines/sogou.ts","../src/libs/browser-search/engines/google.ts","../src/libs/browser-search/engines/get.ts","../src/search/local.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { ISearchRequestOptions, ISearchResponse, SearchProvider } from './interface.js';\nimport { bingSearch, duckDuckGoSearch, searxngSearch, tavilySearch, localSearch } from './search/index.js';\nimport { SEARCH_TOOL, EXTRACT_TOOL, SCRAPE_TOOL, MAP_TOOL } from './tools.js';\nimport FirecrawlApp, { MapParams, ScrapeParams } from '@mendable/firecrawl-js';\nimport dotenvx from '@dotenvx/dotenvx';\nimport { SafeSearchType } from 'duck-duck-scrape';\n\ndotenvx.config();\n\n// search api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: SearchProvider = process.env.SEARCH_PROVIDER as SearchProvider ?? 'searxng';\n\n// search query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\n// firecrawl api\nconst FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;\nconst FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;\n\n// firecrawl client\nconst firecrawl = new FirecrawlApp({\n apiKey: FIRECRAWL_API_KEY ?? '',\n ...(FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}),\n});\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\nconst searchDefaultConfig = {\n limit: Number(LIMIT),\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n MAP_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL,\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\nURL: ${result.url}\nDescription: ${result.snippet}\n${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_scrape': {\n if (!checkScrapeArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const startTime = Date.now();\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping started for url: [${args.url}]`,\n });\n\n const { url, ...scrapeArgs } = args;\n const { content, success, result } = await processScrape(url, scrapeArgs);\n\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping completed in ${Date.now() - startTime}ms`,\n });\n\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error scraping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_map': {\n if (!checkMapArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { content, success, result } = await processMapUrl(args.url, args);\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error mapping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default: {\n throw new Error(`Unknown tool: ${name}`);\n }\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng': {\n // merge default config with args\n const params = {\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n };\n\n // but categories and language have higher priority (ENV > args).\n const { categories, language } = searchDefaultConfig;\n\n if (categories) {\n params.categories = categories;\n }\n if (language) {\n params.language = language;\n }\n return await searxngSearch(params);\n }\n case 'tavily': {\n return await tavilySearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n }\n case 'bing': {\n return await bingSearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n }\n case 'duckduckgo': {\n const safeSearch = args.safeSearch ?? 0;\n const safeSearchOptions = [SafeSearchType.STRICT, SafeSearchType.MODERATE, SafeSearchType.OFF];\n return await duckDuckGoSearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n safeSearch: safeSearchOptions[safeSearch],\n });\n }\n case 'local': {\n return await localSearch({\n ...searchDefaultConfig,\n ...args,\n });\n }\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nasync function processScrape(url: string, args: ScrapeParams) {\n const res = await firecrawl.scrapeUrl(url, {\n ...args,\n });\n\n if (!res.success) {\n throw new Error(`Failed to scrape: ${res.error}`);\n }\n\n const content: string[] = [];\n\n if (res.markdown) {\n content.push(res.markdown);\n }\n\n if (res.rawHtml) {\n content.push(res.rawHtml);\n }\n\n if (res.links) {\n content.push(res.links.join('\\n'));\n }\n\n if (res.screenshot) {\n content.push(res.screenshot);\n }\n\n if (res.html) {\n content.push(res.html);\n }\n\n if (res.extract) {\n content.push(res.extract);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: content.join('\\n\\n') || 'No content found',\n },\n ],\n result: res,\n success: true,\n };\n}\n\nasync function processMapUrl(url: string, args: MapParams) {\n const res = await firecrawl.mapUrl(url, {\n ...args,\n });\n\n if ('error' in res) {\n throw new Error(`Failed to map: ${res.error}`);\n }\n\n if (!res.links) {\n throw new Error(`No links found from: ${url}`);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: res.links.join('\\n').trim(),\n },\n ],\n result: res.links,\n success: true,\n };\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nfunction checkScrapeArgs(args: unknown): args is ScrapeParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nfunction checkMapArgs(args: unknown): args is MapParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","/**\n * Bing Search API\n */\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n\n/**\n * Options for performing a Bing search\n */\nexport interface BingSearchOptions {\n /**\n * Search query string\n */\n q: string;\n\n /**\n * Number of results to return\n */\n count?: number;\n\n /**\n * Result offset for pagination\n */\n offset?: number;\n\n /**\n * Market code (e.g., 'en-US')\n */\n mkt?: string;\n\n /**\n * Safe search filtering level\n */\n safeSearch?: 'Off' | 'Moderate' | 'Strict';\n\n /**\n * Bing API key\n */\n apiKey: string;\n\n /**\n * Bing Search API URL\n */\n apiUrl?: string;\n\n /**\n * Additional parameters supported by Bing Search API\n */\n [key: string]: any;\n}\n\n/**\n * Represents a web page result from Bing Search\n */\nexport interface BingSearchWebPage {\n /**\n * Title of the web page\n */\n name: string;\n\n /**\n * URL of the web page\n */\n url: string;\n\n /**\n * Text snippet from the web page\n */\n snippet: string;\n\n /**\n * Date the page was last crawled by Bing\n */\n dateLastCrawled?: string;\n\n /**\n * Display URL for the web page\n */\n displayUrl?: string;\n\n /**\n * Unique identifier for the result\n */\n id?: string;\n\n /**\n * Indicates if the content is family friendly\n */\n isFamilyFriendly?: boolean;\n\n /**\n * Indicates if the result is navigational\n */\n isNavigational?: boolean;\n\n /**\n * Language of the web page\n */\n language?: string;\n\n /**\n * Indicates if caching should be disabled\n */\n noCache?: boolean;\n\n /**\n * Name of the website\n */\n siteName?: string;\n\n /**\n * URL to a thumbnail image\n */\n thumbnailUrl?: string;\n}\n\n/**\n * Represents an image result from Bing Search\n */\nexport interface BingSearchImage {\n contentSize: string;\n contentUrl: string;\n datePublished: string;\n encodingFormat: string;\n height: number;\n width: number;\n hostPageDisplayUrl: string;\n hostPageUrl: string;\n name: string;\n thumbnail: {\n height: number;\n width: number;\n };\n thumbnailUrl: string;\n webSearchUrl: string;\n}\n\n/**\n * Represents a video result from Bing Search\n */\nexport interface BingSearchVideo {\n allowHttpsEmbed: boolean;\n allowMobileEmbed: boolean;\n contentUrl: string;\n creator?: {\n name: string;\n };\n datePublished: string;\n description: string;\n duration: string;\n embedHtml: string;\n encodingFormat: string;\n height: number;\n width: number;\n hostPageDisplayUrl: string;\n hostPageUrl: string;\n name: string;\n publisher?: {\n name: string;\n }[];\n thumbnail: {\n height: number;\n width: number;\n };\n thumbnailUrl: string;\n viewCount?: number;\n webSearchUrl: string;\n}\n\nexport interface BingSearchResponse {\n _type?: string;\n queryContext?: {\n originalQuery: string;\n };\n webPages?: {\n value: BingSearchWebPage[];\n totalEstimatedMatches?: number;\n someResultsRemoved?: boolean;\n webSearchUrl?: string;\n };\n images?: {\n value: BingSearchImage[];\n isFamilyFriendly?: boolean;\n readLink?: string;\n webSearchUrl?: string;\n id?: string;\n };\n videos?: {\n value: BingSearchVideo[];\n isFamilyFriendly?: boolean;\n readLink?: string;\n webSearchUrl?: string;\n id?: string;\n scenario?: string;\n };\n rankingResponse?: {\n mainline?: {\n items: {\n answerType: string;\n resultIndex?: number;\n value: {\n id: string;\n };\n }[];\n };\n };\n [key: string]: any; // Allow other response fields\n}\n\nexport async function bingSearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const { query, limit = 10, safeSearch = 0, page = 1, apiUrl = 'https://api.bing.microsoft.com/v7.0/search', apiKey, language } = options;\n\n const bingSafeSearchOptions = ['Off', 'Moderate', 'Strict'];\n\n if (!apiKey) {\n throw new Error('Bing API key is required');\n }\n\n const searchOptions = {\n q: query,\n count: limit,\n offset: (page - 1) * limit,\n mkt: language,\n safeSearch: bingSafeSearchOptions[safeSearch] as 'Off' | 'Moderate' | 'Strict',\n };\n\n try {\n const queryParams = new URLSearchParams();\n Object.entries(searchOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.set(key, value.toString());\n }\n });\n\n const res = await fetch(`${apiUrl}?${queryParams}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Ocp-Apim-Subscription-Key': apiKey,\n },\n });\n\n if (!res.ok) {\n throw new Error(`Bing search error: ${res.status} ${res.statusText}`);\n }\n\n const data = await res.json();\n const serp = data.webPages?.value as Array<BingSearchWebPage>;\n const results = serp?.map((item: BingSearchWebPage) => ({\n title: item.name,\n snippet: item.snippet,\n url: item.url,\n source: item.siteName,\n thumbnailUrl: item.thumbnailUrl,\n language: item.language,\n image: null,\n video: null,\n engine: 'bing',\n })) ?? [];\n\n return {\n results,\n success: true,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Bing search error.';\n process.stdout.write(msg);\n throw err;\n }\n}","import * as DDG from 'duck-duck-scrape';\nimport asyncRetry from 'async-retry';\nimport type { SearchOptions } from 'duck-duck-scrape';\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n\nexport async function duckDuckGoSearch(options: Omit<ISearchRequestOptions, 'safeSearch'> & SearchOptions): Promise<ISearchResponse> {\n try {\n const { query, timeout = 10000, safeSearch = DDG.SafeSearchType.OFF, retry = { retries: 3 }, ...searchOptions } = options;\n \n const res = await asyncRetry(\n () => {\n return DDG.search(query, {\n ...searchOptions,\n safeSearch,\n }, {\n // needle options\n response_timeout: timeout,\n });\n },\n retry,\n );\n\n const results = res ? {\n noResults: res.noResults,\n vqd: res.vqd,\n results: res.results,\n } : {\n noResults: true,\n vqd: '',\n results: [],\n };\n\n return {\n results: results.results.map((result) => ({\n title: result.title,\n snippet: result.description,\n url: result.url,\n source: result.hostname,\n image: null,\n video: null,\n engine: 'duckduckgo',\n })),\n success: true,\n };\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'DuckDuckGo search error.';\n process.stdout.write(msg);\n throw error;\n }\n}\n","import url from 'node:url';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from '../interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n page = 1,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: page,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const response = await res.json();\n if (response.results) {\n const list = (response.results as Array<Record<string, any>>).slice(0, limit);\n const results: ISearchResponseResult[] = list.map((item: Record<string, any>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n","import { tavily, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n/**\n * Tavily Search API\n * - https://docs.tavily.com/documentation/quickstart\n */\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n try {\n const tvly = tavily({\n apiKey,\n });\n \n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n \n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n engine: 'tavily',\n }));\n \n return {\n results,\n success: true,\n };\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Tavily search error.';\n process.stdout.write(msg);\n throw error;\n }\n}","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/browser\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { Page, WaitForOptions } from 'puppeteer-core';\n\n/**\n * Options for launching a browser instance\n * @interface LaunchOptions\n */\nexport interface LaunchOptions {\n /**\n * Whether to run browser in headless mode\n * @default false\n */\n headless?: boolean;\n\n /**\n * Maximum time in milliseconds to wait for the browser to start\n * @default 0 (no timeout)\n */\n timeout?: number;\n\n /**\n * The viewport dimensions\n * @property {number} width - Viewport width in pixels\n * @property {number} height - Viewport height in pixels\n */\n defaultViewport?: {\n width: number;\n height: number;\n };\n\n /**\n * Path to a browser executable to use instead of the automatically detected one\n * If not provided, the system will attempt to find an installed browser\n */\n executablePath?: string;\n\n /**\n * Path to a specific browser profile to use\n * Allows using existing browser profiles with cookies, extensions, etc.\n */\n profilePath?: string;\n\n /**\n * Proxy server URL, e.g. 'http://proxy.example.com:8080'\n * Used to route browser traffic through a proxy server\n */\n proxy?: string;\n}\n\n/**\n * Options for evaluating JavaScript in a new page\n * @template T - Array of parameters to pass to the page function\n * @template R - Return type of the page function\n * @interface EvaluateOnNewPageOptions\n */\nexport interface EvaluateOnNewPageOptions<T extends any[], R> {\n /**\n * URL to navigate to before evaluating the function\n * The page will load this URL before executing the pageFunction\n */\n url: string;\n\n /**\n * Options for waiting for the page to load\n */\n waitForOptions?: WaitForOptions;\n\n /**\n * Function to be evaluated in the page context\n * This function runs in the context of the browser page, not Node.js\n * @param {Window} window - The window object of the page\n * @param {...T} args - Additional arguments passed to the function\n * @returns {R} Result of the function execution\n */\n pageFunction: (window: Window, ...args: T) => R;\n\n /**\n * Parameters to pass to the page function\n * These values will be serialized and passed to the pageFunction\n */\n pageFunctionParams: T;\n\n /**\n * Optional function to execute before page navigation\n * Useful for setting up page configuration before loading the URL\n * @param {Page} page - Puppeteer page instance\n * @returns {void | Promise<void>}\n */\n beforePageLoad?: (page: Page) => void | Promise<void>;\n\n /**\n * Optional function to execute after page navigation\n * Useful for setting up page configuration after loading the URL\n * @param {Page} page - Puppeteer page instance\n * @returns {void | Promise<void>}\n */\n afterPageLoad?: (page: Page) => void | Promise<void>;\n\n /**\n * Optional function to process the result before returning\n * Can be used to transform or validate the result from page evaluation\n * @param {Page} page - Puppeteer page instance\n * @param {R} result - Result from page function evaluation\n * @returns {R | Promise<R>} Processed result\n */\n beforeSendResult?: (page: Page, result: R) => R | Promise<R>;\n}\n\n/**\n * Core browser interface that all browser implementations must implement\n * Defines the standard API for browser automation\n * @interface BrowserInterface\n */\nexport interface BrowserInterface {\n /**\n * Launch a new browser instance\n * @param {LaunchOptions} [options] - Launch configuration options\n * @returns {Promise<void>} Promise resolving when browser is launched\n */\n launch(options?: LaunchOptions): Promise<void>;\n\n /**\n * Close the browser instance and all its pages\n * @returns {Promise<void>} Promise resolving when browser is closed\n */\n close(): Promise<void>;\n\n /**\n * Create a new page in the browser\n * @returns {Promise<Page>} Promise resolving to the new page instance\n */\n createPage(): Promise<Page>;\n\n /**\n * Evaluate a function in a new page context\n * Creates a new page, navigates to URL, executes function, and returns result\n * @template T - Array of parameters to pass to the page function\n * @template R - Return type of the page function\n * @param {EvaluateOnNewPageOptions<T, R>} options - Evaluation options\n * @returns {Promise<R | null>} Promise resolving to the function result or null\n */\n evaluateOnNewPage<T extends any[], R>(\n options: EvaluateOnNewPageOptions<T, R>,\n ): Promise<R | null>;\n\n /**\n * Get the currently active page or create one if none exists\n * @returns {Promise<Page>} Promise resolving to the active page instance\n */\n getActivePage(): Promise<Page>;\n}\n\nexport { Page };","/**\n * The following code is modified based on\n * https://github.com/egoist/local-web-search/blob/main/src/find-browser.ts\n * Copy from\n * https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/agent-infra/browser/src/browser-finder.ts\n * \n * MIT Licensed\n * Copyright (c) 2025 ChatWise (https://chatwise.app) <kevin@chatwise.app>\n * https://github.com/egoist/local-web-search/blob/main/LICENSE\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\n\n/**\n * Interface defining browser locations and configurations\n * Contains paths and settings for different operating systems\n * @interface Browser\n */\ninterface Browser {\n /**\n * Browser name identifier\n */\n name: string;\n\n /**\n * Executable paths by platform\n * @property {string} win32 - Windows executable path\n * @property {string} darwin - macOS executable path\n * @property {string} linux - Linux executable path\n */\n executable: {\n win32: string;\n darwin: string;\n linux: string;\n };\n\n /**\n * User data directory paths by platform\n * @property {string} win32 - Windows user data directory\n * @property {string} darwin - macOS user data directory\n * @property {string} linux - Linux user data directory\n */\n userDataDir: {\n win32: string;\n darwin: string;\n linux: string;\n };\n}\n\n/**\n * Class responsible for finding and managing browser installations\n * Detects installed browsers and their profiles across different platforms\n */\nexport class BrowserFinder {\n /**\n * Logger instance for diagnostic output\n */\n private logger: Logger;\n\n /**\n * Creates a new BrowserFinder instance\n * @param {Logger} [logger] - Optional custom logger\n */\n constructor(logger?: Logger) {\n this.logger = logger ?? defaultLogger;\n }\n\n /**\n * Getter that returns the list of supported browsers with their platform-specific paths\n * @returns {Browser[]} Array of browser configurations\n * @private\n */\n private get browsers(): Browser[] {\n // Get HOME_DIR inside the getter to ensure it's always current\n const HOME_DIR = os.homedir();\n const LOCAL_APP_DATA = process.env.LOCALAPPDATA;\n\n return [\n {\n name: 'Chromium',\n executable: {\n win32: 'C:\\\\Program Files\\\\Chromium\\\\Application\\\\chrome.exe',\n darwin: '/Applications/Chromium.app/Contents/MacOS/Chromium',\n linux: '/usr/bin/chromium',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Chromium\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Chromium`,\n linux: `${HOME_DIR}/.config/chromium`,\n },\n },\n {\n name: 'Google Chrome',\n executable: {\n win32: 'C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe',\n darwin:\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n linux: '/usr/bin/google-chrome',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Google\\\\Chrome\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Google/Chrome`,\n linux: `${HOME_DIR}/.config/google-chrome`,\n },\n },\n {\n name: 'Google Chrome Canary',\n executable: {\n win32:\n 'C:\\\\Program Files\\\\Google\\\\Chrome Canary\\\\Application\\\\chrome.exe',\n darwin:\n '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',\n linux: '/usr/bin/google-chrome-canary',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Google\\\\Chrome Canary\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Google/Chrome Canary`,\n linux: `${HOME_DIR}/.config/google-chrome-canary`,\n },\n },\n ];\n }\n\n /**\n * Find a specific browser or the first available browser\n * @param {string} [name] - Optional browser name to find\n * @returns {{ executable: string; userDataDir: string }} Browser executable and user data paths\n * @throws {Error} If no supported browser is found or the platform is unsupported\n */\n findBrowser(name?: string): {\n executable: string;\n userDataDir: string;\n } {\n const platform = process.platform;\n this.logger.info('Finding browser on platform:', platform);\n\n if (platform !== 'darwin' && platform !== 'win32' && platform !== 'linux') {\n const error = new Error(`Unsupported platform: ${platform}`);\n this.logger.error(error.message);\n throw error;\n }\n\n const browser = name\n ? this.browsers.find(\n (b) => b.name === name && fs.existsSync(b.executable[platform]),\n )\n : this.browsers.find((b) => fs.existsSync(b.executable[platform]));\n\n this.logger.log('browser', browser);\n\n if (!browser) {\n const error = name\n ? new Error(`Cannot find browser: ${name}`)\n : new Error(\n 'Cannot find a supported browser on your system. Please install Chrome, Edge, or Brave.',\n );\n this.logger.error(error.message);\n throw error;\n }\n\n const result = {\n executable: browser.executable[platform],\n userDataDir: browser.userDataDir[platform],\n };\n\n this.logger.success(`Found browser: ${browser.name}`);\n this.logger.info('Browser details:', result);\n\n return result;\n }\n\n /**\n * Get browser profiles for a specific browser\n * Reads the Local State file to extract profile information\n * @param {string} [browserName] - Optional browser name to get profiles for\n * @returns {Array<{ displayName: string; path: string }>} Array of profile objects with display names and paths\n */\n getBrowserProfiles(\n browserName?: string,\n ): Array<{ displayName: string; path: string }> {\n const browser = this.findBrowser(browserName);\n\n try {\n const localState = JSON.parse(\n fs.readFileSync(path.join(browser.userDataDir, 'Local State'), 'utf8'),\n );\n const profileInfo = localState.profile.info_cache;\n\n return Object.entries(profileInfo).map(\n ([profileName, info]: [string, any]) => ({\n displayName: info.name,\n path: path.join(browser.userDataDir, profileName),\n }),\n );\n } catch (error) {\n return [];\n }\n }\n\n /**\n * Legacy method for backwards compatibility\n * Finds Chrome browser executable path\n * @deprecated Use findBrowser instead\n * @returns {string | null} Chrome executable path or null if not found\n */\n findChrome(): string | null {\n try {\n const { executable } = this.findBrowser('Google Chrome');\n return executable;\n } catch {\n return null;\n }\n }\n}\n","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/browser\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\nimport {\n BrowserInterface,\n EvaluateOnNewPageOptions,\n LaunchOptions,\n Page,\n} from './types.js';\n\n/**\n * Configuration options for the BaseBrowser class\n * @interface BaseBrowserOptions\n * @property {Logger} [logger] - Custom logger instance to use for browser logging\n */\nexport interface BaseBrowserOptions {\n logger?: Logger;\n}\n\n/**\n * Abstract base class that implements common browser automation functionality\n * Provides a foundation for specific browser implementations with shared capabilities\n * @abstract\n * @implements {BrowserInterface}\n */\nexport abstract class BaseBrowser implements BrowserInterface {\n /**\n * The underlying Puppeteer browser instance\n * @protected\n */\n protected browser: puppeteer.Browser | null = null;\n\n /**\n * Logger instance for browser-related logging\n * @protected\n */\n protected logger: Logger;\n\n /**\n * Reference to the currently active browser page\n * @protected\n */\n protected activePage: Page | null = null;\n\n /**\n * Creates an instance of BaseBrowser\n * @param {BaseBrowserOptions} [options] - Configuration options\n */\n constructor(options?: BaseBrowserOptions) {\n this.logger = options?.logger ?? defaultLogger;\n this.logger.info('Browser Options:', options);\n }\n\n /**\n * Get the underlying Puppeteer browser instance\n * @throws Error if browser is not launched\n\n * @returns {puppeteer.Browser} Puppeteer browser instance\n */\n getBrowser(): puppeteer.Browser {\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n return this.browser;\n }\n\n /**\n * Sets up listeners for browser page events\n * Tracks page creation and updates active page reference\n * @protected\n */\n protected async setupPageListener() {\n if (!this.browser) return;\n\n this.browser.on('targetcreated', async (target) => {\n const page = await target.page();\n if (page) {\n this.logger.info('New page created:', await page.url());\n this.activePage = page;\n\n page.once('close', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n\n page.once('error', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n }\n });\n }\n\n /**\n * Launches the browser with specified options\n * @abstract\n * @param {LaunchOptions} [options] - Browser launch configuration options\n * @returns {Promise<void>} Promise that resolves when browser is launched\n */\n abstract launch(options?: LaunchOptions): Promise<void>;\n\n /**\n * Closes the browser instance and cleans up resources\n * @returns {Promise<void>} Promise that resolves when browser is closed\n * @throws {Error} If browser fails to close properly\n */\n async close(): Promise<void> {\n this.logger.info('Closing browser');\n try {\n await this.browser?.close();\n this.browser = null;\n this.logger.success('Browser closed successfully');\n } catch (error) {\n this.logger.error('Failed to close browser:', error);\n throw error;\n }\n }\n\n /**\n * Creates a new page, navigates to the specified URL, executes a function in the page context, and returns the result\n * This method is inspired and modified from https://github.com/egoist/local-web-search/blob/04608ed09aa103e2fff6402c72ca12edfb692d19/src/browser.ts#L74\n * @template T - Type of parameters passed to the page function\n * @template R - Return type of the page function\n * @param {EvaluateOnNewPageOptions<T, R>} options - Configuration options for the page evaluation\n * @returns {Promise<R | null>} Promise resolving to the result of the page function or null\n * @throws {Error} If page creation or evaluation fails\n */\n async evaluateOnNewPage<T extends any[], R>(\n options: EvaluateOnNewPageOptions<T, R>,\n ): Promise<R | null> {\n const {\n url,\n pageFunction,\n pageFunctionParams,\n beforePageLoad,\n afterPageLoad,\n beforeSendResult,\n waitForOptions,\n } = options;\n const page = await this.browser!.newPage();\n try {\n await beforePageLoad?.(page);\n await page.goto(url, {\n waitUntil: 'networkidle2',\n ...waitForOptions,\n });\n await afterPageLoad?.(page);\n const _window = await page.evaluateHandle(() => window);\n const result = await page.evaluate(\n pageFunction,\n _window,\n ...pageFunctionParams,\n );\n await beforeSendResult?.(page, result);\n await _window.dispose();\n await page.close();\n return result;\n } catch (error) {\n await page.close();\n throw error;\n }\n }\n\n /**\n * Creates a new browser page\n * @returns {Promise<Page>} Promise resolving to the newly created page\n * @throws {Error} If browser is not launched or page creation fails\n */\n async createPage(): Promise<Page> {\n if (!this.browser) {\n this.logger.error('No active browser');\n throw new Error('Browser not launched');\n }\n const page = await this.browser.newPage();\n return page;\n }\n\n /**\n * Gets the currently active page or finds an active page if none is currently tracked\n * If no active pages exist, creates a new page\n * @returns {Promise<Page>} Promise resolving to the active page\n * @throws {Error} If browser is not launched or no active page can be found/created\n */\n async getActivePage(): Promise<Page> {\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n\n // If activePage exists and is still available, return directly\n if (this.activePage) {\n try {\n // Verify that the page is still available\n await this.activePage.evaluate(() => document.readyState);\n return this.activePage;\n } catch (e) {\n this.logger.warn('Active page no longer available:', e);\n this.activePage = null;\n }\n }\n\n // Get all pages and find the last active page\n const pages = await this.browser.pages();\n\n if (pages.length === 0) {\n this.activePage = await this.createPage();\n return this.activePage;\n }\n\n // Find the last responding page\n for (let i = pages.length - 1; i >= 0; i--) {\n const page = pages[i];\n try {\n await page.evaluate(() => document.readyState);\n this.activePage = page;\n return page;\n } catch (e) {\n continue;\n }\n }\n\n throw new Error('No active page found');\n }\n}","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { LaunchOptions } from './types.js';\nimport { BrowserFinder } from './finder.js';\nimport { BaseBrowser } from './base.js';\n\n/**\n * LocalBrowser class for controlling locally installed browsers\n * Extends the BaseBrowser with functionality specific to managing local browser instances\n * @extends BaseBrowser\n */\nexport class LocalBrowser extends BaseBrowser {\n /**\n * Browser finder instance to detect and locate installed browsers\n * @private\n */\n private browserFinder = new BrowserFinder();\n\n /**\n * Launches a local browser instance with specified options\n * Automatically detects installed browsers if no executable path is provided\n * @param {LaunchOptions} options - Configuration options for launching the browser\n * @returns {Promise<void>} Promise that resolves when the browser is successfully launched\n * @throws {Error} If the browser cannot be launched\n */\n async launch(options: LaunchOptions = {}): Promise<void> {\n this.logger.info('Launching browser with options:', options);\n\n const executablePath =\n options?.executablePath || this.browserFinder.findBrowser().executable;\n\n this.logger.info('Using executable path:', executablePath);\n\n const viewportWidth = options?.defaultViewport?.width ?? 1280;\n const viewportHeight = options?.defaultViewport?.height ?? 800;\n\n const puppeteerLaunchOptions: puppeteer.LaunchOptions = {\n executablePath,\n headless: options?.headless ?? false,\n defaultViewport: {\n width: viewportWidth,\n height: viewportHeight,\n },\n args: [\n '--no-sandbox',\n '--mute-audio',\n '--disable-gpu',\n '--disable-http2',\n '--disable-blink-features=AutomationControlled',\n '--disable-infobars',\n '--disable-background-timer-throttling',\n '--disable-popup-blocking',\n '--disable-backgrounding-occluded-windows',\n '--disable-renderer-backgrounding',\n '--disable-window-activation',\n '--disable-focus-on-load',\n '--no-default-browser-check', // disable default browser check\n '--disable-web-security', // disable CORS\n '--disable-features=IsolateOrigins,site-per-process',\n '--disable-site-isolation-trials',\n `--window-size=${viewportWidth},${viewportHeight + 90}`,\n options?.proxy ? `--proxy-server=${options.proxy}` : '',\n options?.profilePath\n ? `--profile-directory=${options.profilePath}`\n : '',\n ].filter(Boolean),\n ignoreDefaultArgs: ['--enable-automation'],\n timeout: options.timeout ?? 0,\n downloadBehavior: {\n policy: 'deny',\n },\n };\n\n this.logger.info('Launch options:', puppeteerLaunchOptions);\n\n try {\n this.browser = await puppeteer.launch(puppeteerLaunchOptions);\n await this.setupPageListener();\n this.logger.success('Browser launched successfully');\n } catch (error) {\n this.logger.error('Failed to launch browser:', error);\n throw error;\n }\n }\n}","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { BaseBrowser, BaseBrowserOptions } from './base.js';\nimport { LaunchOptions } from './types.js';\n\n/**\n * Configuration options for RemoteBrowser\n * @extends BaseBrowserOptions\n * @interface RemoteBrowserOptions\n * @property {string} [wsEndpoint] - WebSocket endpoint URL for direct connection\n * @property {string} [host] - Remote host address (default: 'localhost')\n * @property {number} [port] - Remote debugging port (default: 9222)\n */\nexport interface RemoteBrowserOptions extends BaseBrowserOptions {\n wsEndpoint?: string;\n host?: string;\n port?: number;\n}\n\n/**\n * RemoteBrowser class for connecting to remote browser instances\n *\n * Currently, this RemoteBrowser is not production ready,\n * mainly because it still relies on `puppeteer-core`,\n * which can only run on Node.js.\n *\n * At the same time, Chrome instances built with\n * `--remote-debugging-address` on Linux have security risks\n *\n * @see https://issues.chromium.org/issues/41487252\n * @see https://issues.chromium.org/issues/40261787\n * @see https://github.com/pyppeteer/pyppeteer/pull/379\n * @see https://stackoverflow.com/questions/72760355/chrome-remote-debugging-not-working-computer-to-computer\n *\n * @extends BaseBrowser\n */\nexport class RemoteBrowser extends BaseBrowser {\n /**\n * Creates a new RemoteBrowser instance\n * @param {RemoteBrowserOptions} [options] - Configuration options for remote browser connection\n */\n constructor(private options?: RemoteBrowserOptions) {\n super(options);\n }\n\n /**\n * Connects to a remote browser instance using WebSocket\n * If no WebSocket endpoint is provided, attempts to discover it using the DevTools Protocol\n * @param {LaunchOptions} [options] - Launch configuration options\n * @returns {Promise<void>} Promise that resolves when connected to the remote browser\n * @throws {Error} If connection to the remote browser fails\n */\n async launch(options?: LaunchOptions): Promise<void> {\n this.logger.info('Browser Launch options:', options);\n\n let browserWSEndpoint = this.options?.wsEndpoint;\n\n if (!browserWSEndpoint) {\n const host = this.options?.host || 'localhost';\n const port = this.options?.port || 9222;\n const response = await fetch(`http://${host}:${port}/json/version`);\n const { webSocketDebuggerUrl } = await response.json();\n browserWSEndpoint = webSocketDebuggerUrl;\n }\n\n this.logger.info('Using WebSocket endpoint:', browserWSEndpoint);\n\n const puppeteerConnectOptions: puppeteer.ConnectOptions = {\n browserWSEndpoint,\n defaultViewport: options?.defaultViewport ?? { width: 1280, height: 800 },\n };\n\n try {\n this.browser = await puppeteer.connect(puppeteerConnectOptions);\n await this.setupPageListener();\n this.logger.success('Connected to remote browser successfully');\n } catch (error) {\n this.logger.error('Failed to connect to remote browser:', error);\n throw error;\n }\n }\n}","/**\n * PLEASE DO NOT MODIFY IT as it is generated by the build script\n *\n * Build: scripts/build-readability.ts\n * Source: https://github.com/mozilla/readability/blob/main/Readability.js\n */\n\n/**\n * Copyright (c) 2010 Arc90 Inc\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const READABILITY_SCRIPT =\n 'function q(t,e){if(e&&e.documentElement)t=e,e=arguments[2];else if(!t||!t.documentElement)throw new Error(\"First argument to Readability constructor should be a document object.\");if(e=e||{},this._doc=t,this._docJSDOMParser=this._doc.firstChild.__JSDOMParser__,this._articleTitle=null,this._articleByline=null,this._articleDir=null,this._articleSiteName=null,this._attempts=[],this._debug=!!e.debug,this._maxElemsToParse=e.maxElemsToParse||this.DEFAULT_MAX_ELEMS_TO_PARSE,this._nbTopCandidates=e.nbTopCandidates||this.DEFAULT_N_TOP_CANDIDATES,this._charThreshold=e.charThreshold||this.DEFAULT_CHAR_THRESHOLD,this._classesToPreserve=this.CLASSES_TO_PRESERVE.concat(e.classesToPreserve||[]),this._keepClasses=!!e.keepClasses,this._serializer=e.serializer||function(i){return i.innerHTML},this._disableJSONLD=!!e.disableJSONLD,this._allowedVideoRegex=e.allowedVideoRegex||this.REGEXPS.videos,this._flags=this.FLAG_STRIP_UNLIKELYS|this.FLAG_WEIGHT_CLASSES|this.FLAG_CLEAN_CONDITIONALLY,this._debug){let i=function(r){if(r.nodeType==r.TEXT_NODE)return`${r.nodeName} (\"${r.textContent}\")`;let l=Array.from(r.attributes||[],function(a){return`${a.name}=\"${a.value}\"`}).join(\" \");return`<${r.localName} ${l}>`};this.log=function(){if(typeof console!=\"undefined\"){let l=Array.from(arguments,a=>a&&a.nodeType==this.ELEMENT_NODE?i(a):a);l.unshift(\"Reader: (Readability)\"),console.log.apply(console,l)}else if(typeof dump!=\"undefined\"){var r=Array.prototype.map.call(arguments,function(l){return l&&l.nodeName?i(l):l}).join(\" \");dump(\"Reader: (Readability) \"+r+`\\n`)}}}else this.log=function(){}}q.prototype={FLAG_STRIP_UNLIKELYS:1,FLAG_WEIGHT_CLASSES:2,FLAG_CLEAN_CONDITIONALLY:4,ELEMENT_NODE:1,TEXT_NODE:3,DEFAULT_MAX_ELEMS_TO_PARSE:0,DEFAULT_N_TOP_CANDIDATES:5,DEFAULT_TAGS_TO_SCORE:\"section,h2,h3,h4,h5,h6,p,td,pre\".toUpperCase().split(\",\"),DEFAULT_CHAR_THRESHOLD:500,REGEXPS:{unlikelyCandidates:/-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,okMaybeItsACandidate:/and|article|body|column|content|main|shadow/i,positive:/article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,negative:/-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,extraneous:/print|archive|comment|discuss|e[\\\\-]?mail|share|reply|all|login|sign|single|utility/i,byline:/byline|author|dateline|writtenby|p-author/i,replaceFonts:/<(\\\\/?)font[^>]*>/gi,normalize:/\\\\s{2,}/g,videos:/\\\\/\\\\/(www\\\\.)?((dailymotion|youtube|youtube-nocookie|player\\\\.vimeo|v\\\\.qq)\\\\.com|(archive|upload\\\\.wikimedia)\\\\.org|player\\\\.twitch\\\\.tv)/i,shareElements:/(\\\\b|_)(share|sharedaddy)(\\\\b|_)/i,nextLink:/(next|weiter|continue|>([^\\\\|]|$)|»([^\\\\|]|$))/i,prevLink:/(prev|earl|old|new|<|«)/i,tokenize:/\\\\W+/g,whitespace:/^\\\\s*$/,hasContent:/\\\\S$/,hashUrl:/^#.+/,srcsetUrl:/(\\\\S+)(\\\\s+[\\\\d.]+[xw])?(\\\\s*(?:,|$))/g,b64DataUrl:/^data:\\\\s*([^\\\\s;,]+)\\\\s*;\\\\s*base64\\\\s*,/i,commas:/\\\\u002C|\\\\u060C|\\\\uFE50|\\\\uFE10|\\\\uFE11|\\\\u2E41|\\\\u2E34|\\\\u2E32|\\\\uFF0C/g,jsonLdArticleTypes:/^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/},UNLIKELY_ROLES:[\"menu\",\"menubar\",\"complementary\",\"navigation\",\"alert\",\"alertdialog\",\"dialog\"],DIV_TO_P_ELEMS:new Set([\"BLOCKQUOTE\",\"DL\",\"DIV\",\"IMG\",\"OL\",\"P\",\"PRE\",\"TABLE\",\"UL\"]),ALTER_TO_DIV_EXCEPTIONS:[\"DIV\",\"ARTICLE\",\"SECTION\",\"P\"],PRESENTATIONAL_ATTRIBUTES:[\"align\",\"background\",\"bgcolor\",\"border\",\"cellpadding\",\"cellspacing\",\"frame\",\"hspace\",\"rules\",\"style\",\"valign\",\"vspace\"],DEPRECATED_SIZE_ATTRIBUTE_ELEMS:[\"TABLE\",\"TH\",\"TD\",\"HR\",\"PRE\"],PHRASING_ELEMS:[\"ABBR\",\"AUDIO\",\"B\",\"BDO\",\"BR\",\"BUTTON\",\"CITE\",\"CODE\",\"DATA\",\"DATALIST\",\"DFN\",\"EM\",\"EMBED\",\"I\",\"IMG\",\"INPUT\",\"KBD\",\"LABEL\",\"MARK\",\"MATH\",\"METER\",\"NOSCRIPT\",\"OBJECT\",\"OUTPUT\",\"PROGRESS\",\"Q\",\"RUBY\",\"SAMP\",\"SCRIPT\",\"SELECT\",\"SMALL\",\"SPAN\",\"STRONG\",\"SUB\",\"SUP\",\"TEXTAREA\",\"TIME\",\"VAR\",\"WBR\"],CLASSES_TO_PRESERVE:[\"page\"],HTML_ESCAPE_MAP:{lt:\"<\",gt:\">\",amp:\"&\",quot:\\'\"\\',apos:\"\\'\"},_postProcessContent:function(t){this._fixRelativeUris(t),this._simplifyNestedElements(t),this._keepClasses||this._cleanClasses(t)},_removeNodes:function(t,e){if(this._docJSDOMParser&&t._isLiveNodeList)throw new Error(\"Do not pass live node lists to _removeNodes\");for(var i=t.length-1;i>=0;i--){var r=t[i],l=r.parentNode;l&&(!e||e.call(this,r,i,t))&&l.removeChild(r)}},_replaceNodeTags:function(t,e){if(this._docJSDOMParser&&t._isLiveNodeList)throw new Error(\"Do not pass live node lists to _replaceNodeTags\");for(let i of t)this._setNodeTag(i,e)},_forEachNode:function(t,e){Array.prototype.forEach.call(t,e,this)},_findNode:function(t,e){return Array.prototype.find.call(t,e,this)},_someNode:function(t,e){return Array.prototype.some.call(t,e,this)},_everyNode:function(t,e){return Array.prototype.every.call(t,e,this)},_concatNodeLists:function(){var t=Array.prototype.slice,e=t.call(arguments),i=e.map(function(r){return t.call(r)});return Array.prototype.concat.apply([],i)},_getAllNodesWithTag:function(t,e){return t.querySelectorAll?t.querySelectorAll(e.join(\",\")):[].concat.apply([],e.map(function(i){var r=t.getElementsByTagName(i);return Array.isArray(r)?r:Array.from(r)}))},_cleanClasses:function(t){var e=this._classesToPreserve,i=(t.getAttribute(\"class\")||\"\").split(/\\\\s+/).filter(function(r){return e.indexOf(r)!=-1}).join(\" \");for(i?t.setAttribute(\"class\",i):t.removeAttribute(\"class\"),t=t.firstElementChild;t;t=t.nextElementSibling)this._cleanClasses(t)},_fixRelativeUris:function(t){var e=this._doc.baseURI,i=this._doc.documentURI;function r(s){if(e==i&&s.charAt(0)==\"#\")return s;try{return new URL(s,e).href}catch(h){}return s}var l=this._getAllNodesWithTag(t,[\"a\"]);this._forEachNode(l,function(s){var h=s.getAttribute(\"href\");if(h)if(h.indexOf(\"javascript:\")===0)if(s.childNodes.length===1&&s.childNodes[0].nodeType===this.TEXT_NODE){var c=this._doc.createTextNode(s.textContent);s.parentNode.replaceChild(c,s)}else{for(var n=this._doc.createElement(\"span\");s.firstChild;)n.appendChild(s.firstChild);s.parentNode.replaceChild(n,s)}else s.setAttribute(\"href\",r(h))});var a=this._getAllNodesWithTag(t,[\"img\",\"picture\",\"figure\",\"video\",\"audio\",\"source\"]);this._forEachNode(a,function(s){var h=s.getAttribute(\"src\"),c=s.getAttribute(\"poster\"),n=s.getAttribute(\"srcset\");if(h&&s.setAttribute(\"src\",r(h)),c&&s.setAttribute(\"poster\",r(c)),n){var u=n.replace(this.REGEXPS.srcsetUrl,function(m,b,N,v){return r(b)+(N||\"\")+v});s.setAttribute(\"srcset\",u)}})},_simplifyNestedElements:function(t){for(var e=t;e;){if(e.parentNode&&[\"DIV\",\"SECTION\"].includes(e.tagName)&&!(e.id&&e.id.startsWith(\"readability\"))){if(this._isElementWithoutContent(e)){e=this._removeAndGetNext(e);continue}else if(this._hasSingleTagInsideElement(e,\"DIV\")||this._hasSingleTagInsideElement(e,\"SECTION\")){for(var i=e.children[0],r=0;r<e.attributes.length;r++)i.setAttribute(e.attributes[r].name,e.attributes[r].value);e.parentNode.replaceChild(i,e),e=i;continue}}e=this._getNextNode(e)}},_getArticleTitle:function(){var t=this._doc,e=\"\",i=\"\";try{e=i=t.title.trim(),typeof e!=\"string\"&&(e=i=this._getInnerText(t.getElementsByTagName(\"title\")[0]))}catch(u){}var r=!1;function l(u){return u.split(/\\\\s+/).length}if(/ [\\\\|\\\\-\\\\\\\\\\\\/>»] /.test(e))r=/ [\\\\\\\\\\\\/>»] /.test(e),e=i.replace(/(.*)[\\\\|\\\\-\\\\\\\\\\\\/>»] .*/gi,\"$1\"),l(e)<3&&(e=i.replace(/[^\\\\|\\\\-\\\\\\\\\\\\/>»]*[\\\\|\\\\-\\\\\\\\\\\\/>»](.*)/gi,\"$1\"));else if(e.indexOf(\": \")!==-1){var a=this._concatNodeLists(t.getElementsByTagName(\"h1\"),t.getElementsByTagName(\"h2\")),s=e.trim(),h=this._someNode(a,function(u){return u.textContent.trim()===s});h||(e=i.substring(i.lastIndexOf(\":\")+1),l(e)<3?e=i.substring(i.indexOf(\":\")+1):l(i.substr(0,i.indexOf(\":\")))>5&&(e=i))}else if(e.length>150||e.length<15){var c=t.getElementsByTagName(\"h1\");c.length===1&&(e=this._getInnerText(c[0]))}e=e.trim().replace(this.REGEXPS.normalize,\" \");var n=l(e);return n<=4&&(!r||n!=l(i.replace(/[\\\\|\\\\-\\\\\\\\\\\\/>»]+/g,\"\"))-1)&&(e=i),e},_prepDocument:function(){var t=this._doc;this._removeNodes(this._getAllNodesWithTag(t,[\"style\"])),t.body&&this._replaceBrs(t.body),this._replaceNodeTags(this._getAllNodesWithTag(t,[\"font\"]),\"SPAN\")},_nextNode:function(t){for(var e=t;e&&e.nodeType!=this.ELEMENT_NODE&&this.REGEXPS.whitespace.test(e.textContent);)e=e.nextSibling;return e},_replaceBrs:function(t){this._forEachNode(this._getAllNodesWithTag(t,[\"br\"]),function(e){for(var i=e.nextSibling,r=!1;(i=this._nextNode(i))&&i.tagName==\"BR\";){r=!0;var l=i.nextSibling;i.parentNode.removeChild(i),i=l}if(r){var a=this._doc.createElement(\"p\");for(e.parentNode.replaceChild(a,e),i=a.nextSibling;i;){if(i.tagName==\"BR\"){var s=this._nextNode(i.nextSibling);if(s&&s.tagName==\"BR\")break}if(!this._isPhrasingContent(i))break;var h=i.nextSibling;a.appendChild(i),i=h}for(;a.lastChild&&this._isWhitespace(a.lastChild);)a.removeChild(a.lastChild);a.parentNode.tagName===\"P\"&&this._setNodeTag(a.parentNode,\"DIV\")}})},_setNodeTag:function(t,e){if(this.log(\"_setNodeTag\",t,e),this._docJSDOMParser)return t.localName=e.toLowerCase(),t.tagName=e.toUpperCase(),t;for(var i=t.ownerDocument.createElement(e);t.firstChild;)i.appendChild(t.firstChild);t.parentNode.replaceChild(i,t),t.readability&&(i.readability=t.readability);for(var r=0;r<t.attributes.length;r++)try{i.setAttribute(t.attributes[r].name,t.attributes[r].value)}catch(l){}return i},_prepArticle:function(t){this._cleanStyles(t),this._markDataTables(t),this._fixLazyImages(t),this._cleanConditionally(t,\"form\"),this._cleanConditionally(t,\"fieldset\"),this._clean(t,\"object\"),this._clean(t,\"embed\"),this._clean(t,\"footer\"),this._clean(t,\"link\"),this._clean(t,\"aside\");var e=this.DEFAULT_CHAR_THRESHOLD;this._forEachNode(t.children,function(i){this._cleanMatchedNodes(i,function(r,l){return this.REGEXPS.shareElements.test(l)&&r.textContent.length<e})}),this._clean(t,\"iframe\"),this._clean(t,\"input\"),this._clean(t,\"textarea\"),this._clean(t,\"select\"),this._clean(t,\"button\"),this._cleanHeaders(t),this._cleanConditionally(t,\"table\"),this._cleanConditionally(t,\"ul\"),this._cleanConditionally(t,\"div\"),this._replaceNodeTags(this._getAllNodesWithTag(t,[\"h1\"]),\"h2\"),this._removeNodes(this._getAllNodesWithTag(t,[\"p\"]),function(i){var r=i.getElementsByTagName(\"img\").length,l=i.getElementsByTagName(\"embed\").length,a=i.getElementsByTagName(\"object\").length,s=i.getElementsByTagName(\"iframe\").length,h=r+l+a+s;return h===0&&!this._getInnerText(i,!1)}),this._forEachNode(this._getAllNodesWithTag(t,[\"br\"]),function(i){var r=this._nextNode(i.nextSibling);r&&r.tagName==\"P\"&&i.parentNode.removeChild(i)}),this._forEachNode(this._getAllNodesWithTag(t,[\"table\"]),function(i){var r=this._hasSingleTagInsideElement(i,\"TBODY\")?i.firstElementChild:i;if(this._hasSingleTagInsideElement(r,\"TR\")){var l=r.firstElementChild;if(this._hasSingleTagInsideElement(l,\"TD\")){var a=l.firstElementChild;a=this._setNodeTag(a,this._everyNode(a.childNodes,this._isPhrasingContent)?\"P\":\"DIV\"),i.parentNode.replaceChild(a,i)}}})},_initializeNode:function(t){switch(t.readability={contentScore:0},t.tagName){case\"DIV\":t.readability.contentScore+=5;break;case\"PRE\":case\"TD\":case\"BLOCKQUOTE\":t.readability.contentScore+=3;break;case\"ADDRESS\":case\"OL\":case\"UL\":case\"DL\":case\"DD\":case\"DT\":case\"LI\":case\"FORM\":t.readability.contentScore-=3;break;case\"H1\":case\"H2\":case\"H3\":case\"H4\":case\"H5\":case\"H6\":case\"TH\":t.readability.contentScore-=5;break}t.readability.contentScore+=this._getClassWeight(t)},_removeAndGetNext:function(t){var e=this._getNextNode(t,!0);return t.parentNode.removeChild(t),e},_getNextNode:function(t,e){if(!e&&t.firstElementChild)return t.firstElementChild;if(t.nextElementSibling)return t.nextElementSibling;do t=t.parentNode;while(t&&!t.nextElementSibling);return t&&t.nextElementSibling},_textSimilarity:function(t,e){var i=t.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean),r=e.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);if(!i.length||!r.length)return 0;var l=r.filter(s=>!i.includes(s)),a=l.join(\" \").length/r.join(\" \").length;return 1-a},_checkByline:function(t,e){if(this._articleByline)return!1;if(t.getAttribute!==void 0)var i=t.getAttribute(\"rel\"),r=t.getAttribute(\"itemprop\");return(i===\"author\"||r&&r.indexOf(\"author\")!==-1||this.REGEXPS.byline.test(e))&&this._isValidByline(t.textContent)?(this._articleByline=t.textContent.trim(),!0):!1},_getNodeAncestors:function(t,e){e=e||0;for(var i=0,r=[];t.parentNode&&(r.push(t.parentNode),!(e&&++i===e));)t=t.parentNode;return r},_grabArticle:function(t){this.log(\"**** grabArticle ****\");var e=this._doc,i=t!==null;if(t=t||this._doc.body,!t)return this.log(\"No body found in document. Abort.\"),null;for(var r=t.innerHTML;;){this.log(\"Starting grabArticle loop\");var l=this._flagIsActive(this.FLAG_STRIP_UNLIKELYS),a=[],s=this._doc.documentElement;let J=!0;for(;s;){s.tagName===\"HTML\"&&(this._articleLang=s.getAttribute(\"lang\"));var h=s.className+\" \"+s.id;if(!this._isProbablyVisible(s)){this.log(\"Removing hidden node - \"+h),s=this._removeAndGetNext(s);continue}if(s.getAttribute(\"aria-modal\")==\"true\"&&s.getAttribute(\"role\")==\"dialog\"){s=this._removeAndGetNext(s);continue}if(this._checkByline(s,h)){s=this._removeAndGetNext(s);continue}if(J&&this._headerDuplicatesTitle(s)){this.log(\"Removing header: \",s.textContent.trim(),this._articleTitle.trim()),J=!1,s=this._removeAndGetNext(s);continue}if(l){if(this.REGEXPS.unlikelyCandidates.test(h)&&!this.REGEXPS.okMaybeItsACandidate.test(h)&&!this._hasAncestorTag(s,\"table\")&&!this._hasAncestorTag(s,\"code\")&&s.tagName!==\"BODY\"&&s.tagName!==\"A\"){this.log(\"Removing unlikely candidate - \"+h),s=this._removeAndGetNext(s);continue}if(this.UNLIKELY_ROLES.includes(s.getAttribute(\"role\"))){this.log(\"Removing content with role \"+s.getAttribute(\"role\")+\" - \"+h),s=this._removeAndGetNext(s);continue}}if((s.tagName===\"DIV\"||s.tagName===\"SECTION\"||s.tagName===\"HEADER\"||s.tagName===\"H1\"||s.tagName===\"H2\"||s.tagName===\"H3\"||s.tagName===\"H4\"||s.tagName===\"H5\"||s.tagName===\"H6\")&&this._isElementWithoutContent(s)){s=this._removeAndGetNext(s);continue}if(this.DEFAULT_TAGS_TO_SCORE.indexOf(s.tagName)!==-1&&a.push(s),s.tagName===\"DIV\"){for(var c=null,n=s.firstChild;n;){var u=n.nextSibling;if(this._isPhrasingContent(n))c!==null?c.appendChild(n):this._isWhitespace(n)||(c=e.createElement(\"p\"),s.replaceChild(c,n),c.appendChild(n));else if(c!==null){for(;c.lastChild&&this._isWhitespace(c.lastChild);)c.removeChild(c.lastChild);c=null}n=u}if(this._hasSingleTagInsideElement(s,\"P\")&&this._getLinkDensity(s)<.25){var m=s.children[0];s.parentNode.replaceChild(m,s),s=m,a.push(s)}else this._hasChildBlockElement(s)||(s=this._setNodeTag(s,\"P\"),a.push(s))}s=this._getNextNode(s)}var b=[];this._forEachNode(a,function(A){if(!(!A.parentNode||typeof A.parentNode.tagName==\"undefined\")){var T=this._getInnerText(A);if(!(T.length<25)){var K=this._getNodeAncestors(A,5);if(K.length!==0){var C=0;C+=1,C+=T.split(this.REGEXPS.commas).length,C+=Math.min(Math.floor(T.length/100),3),this._forEachNode(K,function(S,F){if(!(!S.tagName||!S.parentNode||typeof S.parentNode.tagName==\"undefined\")){if(typeof S.readability==\"undefined\"&&(this._initializeNode(S),b.push(S)),F===0)var X=1;else F===1?X=2:X=F*3;S.readability.contentScore+=C/X}})}}}});for(var N=[],v=0,y=b.length;v<y;v+=1){var E=b[v],d=E.readability.contentScore*(1-this._getLinkDensity(E));E.readability.contentScore=d,this.log(\"Candidate:\",E,\"with score \"+d);for(var p=0;p<this._nbTopCandidates;p++){var x=N[p];if(!x||d>x.readability.contentScore){N.splice(p,0,E),N.length>this._nbTopCandidates&&N.pop();break}}}var o=N[0]||null,L=!1,g;if(o===null||o.tagName===\"BODY\"){for(o=e.createElement(\"DIV\"),L=!0;t.firstChild;)this.log(\"Moving child out:\",t.firstChild),o.appendChild(t.firstChild);t.appendChild(o),this._initializeNode(o)}else if(o){for(var I=[],P=1;P<N.length;P++)N[P].readability.contentScore/o.readability.contentScore>=.75&&I.push(this._getNodeAncestors(N[P]));var O=3;if(I.length>=O)for(g=o.parentNode;g.tagName!==\"BODY\";){for(var G=0,H=0;H<I.length&&G<O;H++)G+=Number(I[H].includes(g));if(G>=O){o=g;break}g=g.parentNode}o.readability||this._initializeNode(o),g=o.parentNode;for(var M=o.readability.contentScore,Q=M/3;g.tagName!==\"BODY\";){if(!g.readability){g=g.parentNode;continue}var V=g.readability.contentScore;if(V<Q)break;if(V>M){o=g;break}M=g.readability.contentScore,g=g.parentNode}for(g=o.parentNode;g.tagName!=\"BODY\"&&g.children.length==1;)o=g,g=o.parentNode;o.readability||this._initializeNode(o)}var _=e.createElement(\"DIV\");i&&(_.id=\"readability-content\");var Z=Math.max(10,o.readability.contentScore*.2);g=o.parentNode;for(var U=g.children,w=0,j=U.length;w<j;w++){var f=U[w],R=!1;if(this.log(\"Looking at sibling node:\",f,f.readability?\"with score \"+f.readability.contentScore:\"\"),this.log(\"Sibling has score\",f.readability?f.readability.contentScore:\"Unknown\"),f===o)R=!0;else{var $=0;if(f.className===o.className&&o.className!==\"\"&&($+=o.readability.contentScore*.2),f.readability&&f.readability.contentScore+$>=Z)R=!0;else if(f.nodeName===\"P\"){var Y=this._getLinkDensity(f),z=this._getInnerText(f),k=z.length;(k>80&&Y<.25||k<80&&k>0&&Y===0&&z.search(/\\\\.( |$)/)!==-1)&&(R=!0)}}R&&(this.log(\"Appending node:\",f),this.ALTER_TO_DIV_EXCEPTIONS.indexOf(f.nodeName)===-1&&(this.log(\"Altering sibling:\",f,\"to div.\"),f=this._setNodeTag(f,\"DIV\")),_.appendChild(f),U=g.children,w-=1,j-=1)}if(this._debug&&this.log(\"Article content pre-prep: \"+_.innerHTML),this._prepArticle(_),this._debug&&this.log(\"Article content post-prep: \"+_.innerHTML),L)o.id=\"readability-page-1\",o.className=\"page\";else{var B=e.createElement(\"DIV\");for(B.id=\"readability-page-1\",B.className=\"page\";_.firstChild;)B.appendChild(_.firstChild);_.appendChild(B)}this._debug&&this.log(\"Article content after paging: \"+_.innerHTML);var W=!0,D=this._getInnerText(_,!0).length;if(D<this._charThreshold)if(W=!1,t.innerHTML=r,this._flagIsActive(this.FLAG_STRIP_UNLIKELYS))this._removeFlag(this.FLAG_STRIP_UNLIKELYS),this._attempts.push({articleContent:_,textLength:D});else if(this._flagIsActive(this.FLAG_WEIGHT_CLASSES))this._removeFlag(this.FLAG_WEIGHT_CLASSES),this._attempts.push({articleContent:_,textLength:D});else if(this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY))this._removeFlag(this.FLAG_CLEAN_CONDITIONALLY),this._attempts.push({articleContent:_,textLength:D});else{if(this._attempts.push({articleContent:_,textLength:D}),this._attempts.sort(function(A,T){return T.textLength-A.textLength}),!this._attempts[0].textLength)return null;_=this._attempts[0].articleContent,W=!0}if(W){var tt=[g,o].concat(this._getNodeAncestors(g));return this._someNode(tt,function(A){if(!A.tagName)return!1;var T=A.getAttribute(\"dir\");return T?(this._articleDir=T,!0):!1}),_}}},_isValidByline:function(t){return typeof t==\"string\"||t instanceof String?(t=t.trim(),t.length>0&&t.length<100):!1},_unescapeHtmlEntities:function(t){if(!t)return t;var e=this.HTML_ESCAPE_MAP;return t.replace(/&(quot|amp|apos|lt|gt);/g,function(i,r){return e[r]}).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi,function(i,r,l){var a=parseInt(r||l,r?16:10);return String.fromCharCode(a)})},_getJSONLD:function(t){var e=this._getAllNodesWithTag(t,[\"script\"]),i;return this._forEachNode(e,function(r){if(!i&&r.getAttribute(\"type\")===\"application/ld+json\")try{var l=r.textContent.replace(/^\\\\s*<!\\\\[CDATA\\\\[|\\\\]\\\\]>\\\\s*$/g,\"\"),a=JSON.parse(l);if(!a[\"@context\"]||!a[\"@context\"].match(/^https?\\\\:\\\\/\\\\/schema\\\\.org$/)||(!a[\"@type\"]&&Array.isArray(a[\"@graph\"])&&(a=a[\"@graph\"].find(function(n){return(n[\"@type\"]||\"\").match(this.REGEXPS.jsonLdArticleTypes)})),!a||!a[\"@type\"]||!a[\"@type\"].match(this.REGEXPS.jsonLdArticleTypes)))return;if(i={},typeof a.name==\"string\"&&typeof a.headline==\"string\"&&a.name!==a.headline){var s=this._getArticleTitle(),h=this._textSimilarity(a.name,s)>.75,c=this._textSimilarity(a.headline,s)>.75;c&&!h?i.title=a.headline:i.title=a.name}else typeof a.name==\"string\"?i.title=a.name.trim():typeof a.headline==\"string\"&&(i.title=a.headline.trim());a.author&&(typeof a.author.name==\"string\"?i.byline=a.author.name.trim():Array.isArray(a.author)&&a.author[0]&&typeof a.author[0].name==\"string\"&&(i.byline=a.author.filter(function(n){return n&&typeof n.name==\"string\"}).map(function(n){return n.name.trim()}).join(\", \"))),typeof a.description==\"string\"&&(i.excerpt=a.description.trim()),a.publisher&&typeof a.publisher.name==\"string\"&&(i.siteName=a.publisher.name.trim()),typeof a.datePublished==\"string\"&&(i.datePublished=a.datePublished.trim());return}catch(n){this.log(n.message)}}),i||{}},_getArticleMetadata:function(t){var e={},i={},r=this._doc.getElementsByTagName(\"meta\"),l=/\\\\s*(article|dc|dcterm|og|twitter)\\\\s*:\\\\s*(author|creator|description|published_time|title|site_name)\\\\s*/gi,a=/^\\\\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\\\\s*[\\\\.:]\\\\s*)?(author|creator|description|title|site_name)\\\\s*$/i;return this._forEachNode(r,function(s){var h=s.getAttribute(\"name\"),c=s.getAttribute(\"property\"),n=s.getAttribute(\"content\");if(n){var u=null,m=null;c&&(u=c.match(l),u&&(m=u[0].toLowerCase().replace(/\\\\s/g,\"\"),i[m]=n.trim())),!u&&h&&a.test(h)&&(m=h,n&&(m=m.toLowerCase().replace(/\\\\s/g,\"\").replace(/\\\\./g,\":\"),i[m]=n.trim()))}}),e.title=t.title||i[\"dc:title\"]||i[\"dcterm:title\"]||i[\"og:title\"]||i[\"weibo:article:title\"]||i[\"weibo:webpage:title\"]||i.title||i[\"twitter:title\"],e.title||(e.title=this._getArticleTitle()),e.byline=t.byline||i[\"dc:creator\"]||i[\"dcterm:creator\"]||i.author,e.excerpt=t.excerpt||i[\"dc:description\"]||i[\"dcterm:description\"]||i[\"og:description\"]||i[\"weibo:article:description\"]||i[\"weibo:webpage:description\"]||i.description||i[\"twitter:description\"],e.siteName=t.siteName||i[\"og:site_name\"],e.publishedTime=t.datePublished||i[\"article:published_time\"]||null,e.title=this._unescapeHtmlEntities(e.title),e.byline=this._unescapeHtmlEntities(e.byline),e.excerpt=this._unescapeHtmlEntities(e.excerpt),e.siteName=this._unescapeHtmlEntities(e.siteName),e.publishedTime=this._unescapeHtmlEntities(e.publishedTime),e},_isSingleImage:function(t){return t.tagName===\"IMG\"?!0:t.children.length!==1||t.textContent.trim()!==\"\"?!1:this._isSingleImage(t.children[0])},_unwrapNoscriptImages:function(t){var e=Array.from(t.getElementsByTagName(\"img\"));this._forEachNode(e,function(r){for(var l=0;l<r.attributes.length;l++){var a=r.attributes[l];switch(a.name){case\"src\":case\"srcset\":case\"data-src\":case\"data-srcset\":return}if(/\\\\.(jpg|jpeg|png|webp)/i.test(a.value))return}r.parentNode.removeChild(r)});var i=Array.from(t.getElementsByTagName(\"noscript\"));this._forEachNode(i,function(r){var l=t.createElement(\"div\");if(l.innerHTML=r.innerHTML,!!this._isSingleImage(l)){var a=r.previousElementSibling;if(a&&this._isSingleImage(a)){var s=a;s.tagName!==\"IMG\"&&(s=a.getElementsByTagName(\"img\")[0]);for(var h=l.getElementsByTagName(\"img\")[0],c=0;c<s.attributes.length;c++){var n=s.attributes[c];if(n.value!==\"\"&&(n.name===\"src\"||n.name===\"srcset\"||/\\\\.(jpg|jpeg|png|webp)/i.test(n.value))){if(h.getAttribute(n.name)===n.value)continue;var u=n.name;h.hasAttribute(u)&&(u=\"data-old-\"+u),h.setAttribute(u,n.value)}}r.parentNode.replaceChild(l.firstElementChild,a)}}})},_removeScripts:function(t){this._removeNodes(this._getAllNodesWithTag(t,[\"script\",\"noscript\"]))},_hasSingleTagInsideElement:function(t,e){return t.children.length!=1||t.children[0].tagName!==e?!1:!this._someNode(t.childNodes,function(i){return i.nodeType===this.TEXT_NODE&&this.REGEXPS.hasContent.test(i.textContent)})},_isElementWithoutContent:function(t){return t.nodeType===this.ELEMENT_NODE&&t.textContent.trim().length==0&&(t.children.length==0||t.children.length==t.getElementsByTagName(\"br\").length+t.getElementsByTagName(\"hr\").length)},_hasChildBlockElement:function(t){return this._someNode(t.childNodes,function(e){return this.DIV_TO_P_ELEMS.has(e.tagName)||this._hasChildBlockElement(e)})},_isPhrasingContent:function(t){return t.nodeType===this.TEXT_NODE||this.PHRASING_ELEMS.indexOf(t.tagName)!==-1||(t.tagName===\"A\"||t.tagName===\"DEL\"||t.tagName===\"INS\")&&this._everyNode(t.childNodes,this._isPhrasingContent)},_isWhitespace:function(t){return t.nodeType===this.TEXT_NODE&&t.textContent.trim().length===0||t.nodeType===this.ELEMENT_NODE&&t.tagName===\"BR\"},_getInnerText:function(t,e){e=typeof e==\"undefined\"?!0:e;var i=t.textContent.trim();return e?i.replace(this.REGEXPS.normalize,\" \"):i},_getCharCount:function(t,e){return e=e||\",\",this._getInnerText(t).split(e).length-1},_cleanStyles:function(t){if(!(!t||t.tagName.toLowerCase()===\"svg\")){for(var e=0;e<this.PRESENTATIONAL_ATTRIBUTES.length;e++)t.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[e]);this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(t.tagName)!==-1&&(t.removeAttribute(\"width\"),t.removeAttribute(\"height\"));for(var i=t.firstElementChild;i!==null;)this._cleanStyles(i),i=i.nextElementSibling}},_getLinkDensity:function(t){var e=this._getInnerText(t).length;if(e===0)return 0;var i=0;return this._forEachNode(t.getElementsByTagName(\"a\"),function(r){var l=r.getAttribute(\"href\"),a=l&&this.REGEXPS.hashUrl.test(l)?.3:1;i+=this._getInnerText(r).length*a}),i/e},_getClassWeight:function(t){if(!this._flagIsActive(this.FLAG_WEIGHT_CLASSES))return 0;var e=0;return typeof t.className==\"string\"&&t.className!==\"\"&&(this.REGEXPS.negative.test(t.className)&&(e-=25),this.REGEXPS.positive.test(t.className)&&(e+=25)),typeof t.id==\"string\"&&t.id!==\"\"&&(this.REGEXPS.negative.test(t.id)&&(e-=25),this.REGEXPS.positive.test(t.id)&&(e+=25)),e},_clean:function(t,e){var i=[\"object\",\"embed\",\"iframe\"].indexOf(e)!==-1;this._removeNodes(this._getAllNodesWithTag(t,[e]),function(r){if(i){for(var l=0;l<r.attributes.length;l++)if(this._allowedVideoRegex.test(r.attributes[l].value))return!1;if(r.tagName===\"object\"&&this._allowedVideoRegex.test(r.innerHTML))return!1}return!0})},_hasAncestorTag:function(t,e,i,r){i=i||3,e=e.toUpperCase();for(var l=0;t.parentNode;){if(i>0&&l>i)return!1;if(t.parentNode.tagName===e&&(!r||r(t.parentNode)))return!0;t=t.parentNode,l++}return!1},_getRowAndColumnCount:function(t){for(var e=0,i=0,r=t.getElementsByTagName(\"tr\"),l=0;l<r.length;l++){var a=r[l].getAttribute(\"rowspan\")||0;a&&(a=parseInt(a,10)),e+=a||1;for(var s=0,h=r[l].getElementsByTagName(\"td\"),c=0;c<h.length;c++){var n=h[c].getAttribute(\"colspan\")||0;n&&(n=parseInt(n,10)),s+=n||1}i=Math.max(i,s)}return{rows:e,columns:i}},_markDataTables:function(t){for(var e=t.getElementsByTagName(\"table\"),i=0;i<e.length;i++){var r=e[i],l=r.getAttribute(\"role\");if(l==\"presentation\"){r._readabilityDataTable=!1;continue}var a=r.getAttribute(\"datatable\");if(a==\"0\"){r._readabilityDataTable=!1;continue}var s=r.getAttribute(\"summary\");if(s){r._readabilityDataTable=!0;continue}var h=r.getElementsByTagName(\"caption\")[0];if(h&&h.childNodes.length>0){r._readabilityDataTable=!0;continue}var c=[\"col\",\"colgroup\",\"tfoot\",\"thead\",\"th\"],n=function(m){return!!r.getElementsByTagName(m)[0]};if(c.some(n)){this.log(\"Data table because found data-y descendant\"),r._readabilityDataTable=!0;continue}if(r.getElementsByTagName(\"table\")[0]){r._readabilityDataTable=!1;continue}var u=this._getRowAndColumnCount(r);if(u.rows>=10||u.columns>4){r._readabilityDataTable=!0;continue}r._readabilityDataTable=u.rows*u.columns>10}},_fixLazyImages:function(t){this._forEachNode(this._getAllNodesWithTag(t,[\"img\",\"picture\",\"figure\"]),function(e){if(e.src&&this.REGEXPS.b64DataUrl.test(e.src)){var i=this.REGEXPS.b64DataUrl.exec(e.src);if(i[1]===\"image/svg+xml\")return;for(var r=!1,l=0;l<e.attributes.length;l++){var a=e.attributes[l];if(a.name!==\"src\"&&/\\\\.(jpg|jpeg|png|webp)/i.test(a.value)){r=!0;break}}if(r){var s=e.src.search(/base64\\\\s*/i)+7,h=e.src.length-s;h<133&&e.removeAttribute(\"src\")}}if(!((e.src||e.srcset&&e.srcset!=\"null\")&&e.className.toLowerCase().indexOf(\"lazy\")===-1)){for(var c=0;c<e.attributes.length;c++)if(a=e.attributes[c],!(a.name===\"src\"||a.name===\"srcset\"||a.name===\"alt\")){var n=null;if(/\\\\.(jpg|jpeg|png|webp)\\\\s+\\\\d/.test(a.value)?n=\"srcset\":/^\\\\s*\\\\S+\\\\.(jpg|jpeg|png|webp)\\\\S*\\\\s*$/.test(a.value)&&(n=\"src\"),n){if(e.tagName===\"IMG\"||e.tagName===\"PICTURE\")e.setAttribute(n,a.value);else if(e.tagName===\"FIGURE\"&&!this._getAllNodesWithTag(e,[\"img\",\"picture\"]).length){var u=this._doc.createElement(\"img\");u.setAttribute(n,a.value),e.appendChild(u)}}}}})},_getTextDensity:function(t,e){var i=this._getInnerText(t,!0).length;if(i===0)return 0;var r=0,l=this._getAllNodesWithTag(t,e);return this._forEachNode(l,a=>r+=this._getInnerText(a,!0).length),r/i},_cleanConditionally:function(t,e){this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)&&this._removeNodes(this._getAllNodesWithTag(t,[e]),function(i){var r=function(g){return g._readabilityDataTable},l=e===\"ul\"||e===\"ol\";if(!l){var a=0,s=this._getAllNodesWithTag(i,[\"ul\",\"ol\"]);this._forEachNode(s,g=>a+=this._getInnerText(g).length),l=a/this._getInnerText(i).length>.9}if(e===\"table\"&&r(i)||this._hasAncestorTag(i,\"table\",-1,r)||this._hasAncestorTag(i,\"code\"))return!1;var h=this._getClassWeight(i);this.log(\"Cleaning Conditionally\",i);var c=0;if(h+c<0)return!0;if(this._getCharCount(i,\",\")<10){for(var n=i.getElementsByTagName(\"p\").length,u=i.getElementsByTagName(\"img\").length,m=i.getElementsByTagName(\"li\").length-100,b=i.getElementsByTagName(\"input\").length,N=this._getTextDensity(i,[\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\"]),v=0,y=this._getAllNodesWithTag(i,[\"object\",\"embed\",\"iframe\"]),E=0;E<y.length;E++){for(var d=0;d<y[E].attributes.length;d++)if(this._allowedVideoRegex.test(y[E].attributes[d].value))return!1;if(y[E].tagName===\"object\"&&this._allowedVideoRegex.test(y[E].innerHTML))return!1;v++}var p=this._getLinkDensity(i),x=this._getInnerText(i).length,o=u>1&&n/u<.5&&!this._hasAncestorTag(i,\"figure\")||!l&&m>n||b>Math.floor(n/3)||!l&&N<.9&&x<25&&(u===0||u>2)&&!this._hasAncestorTag(i,\"figure\")||!l&&h<25&&p>.2||h>=25&&p>.5||v===1&&x<75||v>1;if(l&&o){for(var L=0;L<i.children.length;L++)if(i.children[L].children.length>1)return o;let g=i.getElementsByTagName(\"li\").length;if(u==g)return!1}return o}return!1})},_cleanMatchedNodes:function(t,e){for(var i=this._getNextNode(t,!0),r=this._getNextNode(t);r&&r!=i;)e.call(this,r,r.className+\" \"+r.id)?r=this._removeAndGetNext(r):r=this._getNextNode(r)},_cleanHeaders:function(t){let e=this._getAllNodesWithTag(t,[\"h1\",\"h2\"]);this._removeNodes(e,function(i){let r=this._getClassWeight(i)<0;return r&&this.log(\"Removing header with low class weight:\",i),r})},_headerDuplicatesTitle:function(t){if(t.tagName!=\"H1\"&&t.tagName!=\"H2\")return!1;var e=this._getInnerText(t,!1);return this.log(\"Evaluating similarity of header:\",e,this._articleTitle),this._textSimilarity(this._articleTitle,e)>.75},_flagIsActive:function(t){return(this._flags&t)>0},_removeFlag:function(t){this._flags=this._flags&~t},_isProbablyVisible:function(t){return(!t.style||t.style.display!=\"none\")&&(!t.style||t.style.visibility!=\"hidden\")&&!t.hasAttribute(\"hidden\")&&(!t.hasAttribute(\"aria-hidden\")||t.getAttribute(\"aria-hidden\")!=\"true\"||t.className&&t.className.indexOf&&t.className.indexOf(\"fallback-image\")!==-1)},parse:function(){if(this._maxElemsToParse>0){var t=this._doc.getElementsByTagName(\"*\").length;if(t>this._maxElemsToParse)throw new Error(\"Aborting parsing document; \"+t+\" elements found\")}this._unwrapNoscriptImages(this._doc);var e=this._disableJSONLD?{}:this._getJSONLD(this._doc);this._removeScripts(this._doc),this._prepDocument();var i=this._getArticleMetadata(e);this._articleTitle=i.title;var r=this._grabArticle();if(!r)return null;if(this.log(\"Grabbed: \"+r.innerHTML),this._postProcessContent(r),!i.excerpt){var l=r.getElementsByTagName(\"p\");l.length>0&&(i.excerpt=l[0].textContent.trim())}var a=r.textContent;return{title:this._articleTitle,byline:i.byline||this._articleByline,dir:this._articleDir,lang:this._articleLang,content:this._serializer(r),textContent:a,length:a.length,excerpt:i.excerpt,siteName:i.siteName||this._articleSiteName,publishedTime:i.publishedTime}}};typeof module==\"object\"&&(module.exports=q);\\n';","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { LocalBrowser, type BrowserInterface } from '../browser/index.js';\nimport { READABILITY_SCRIPT } from './readability.js';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\nimport {\n extractPageInformation,\n toMarkdown,\n} from './utils.js';\nimport { PromiseQueue } from './queue.js';\nimport { shouldSkipDomain, interceptRequest } from './utils.js';\nimport { getSearchEngine } from './engines/index.js';\nimport type {\n SearchResult,\n BrowserSearchOptions,\n BrowserSearchConfig,\n LocalBrowserSearchEngine,\n} from './types.js';\n\n/**\n * Service class for performing web searches and content extraction\n */\nexport class BrowserSearch {\n private logger: Logger;\n private browser: BrowserInterface;\n private isBrowserOpen = false;\n private defaultEngine: LocalBrowserSearchEngine;\n\n constructor(private config: BrowserSearchConfig = {}) {\n this.logger = config?.logger ?? defaultLogger;\n this.browser = config.browser ?? new LocalBrowser({ logger: this.logger });\n this.defaultEngine = config.defaultEngine ?? 'bing';\n }\n\n /**\n * Search web and extract content from result pages\n */\n async perform(options: BrowserSearchOptions) {\n this.logger.info('Starting search with options:', options);\n\n const queries = Array.isArray(options.query)\n ? options.query\n : [options.query];\n const excludeDomains = options.excludeDomains || [];\n const count =\n options.count && Math.max(3, Math.floor(options.count / queries.length));\n const engine = options.engine || this.defaultEngine;\n\n try {\n if (!this.isBrowserOpen) {\n this.logger.info('Launching browser');\n await this.browser.launch(this.config.browserOptions);\n this.isBrowserOpen = true;\n } else {\n this.logger.info('Using existing browser instance');\n }\n\n const queue = new PromiseQueue(options.concurrency || 15);\n const visitedUrls = new Set<string>();\n const results = await Promise.all(\n queries.map((query) =>\n this.search(this.browser, {\n query,\n count,\n queue,\n visitedUrls,\n excludeDomains,\n truncate: options.truncate,\n needVisitedUrls: options.needVisitedUrls,\n engine,\n }),\n ),\n );\n\n this.logger.success('Search completed successfully');\n return results.flat();\n } catch (error) {\n this.logger.error('Search failed:', error);\n return [];\n } finally {\n if (!options.keepBrowserOpen && this.isBrowserOpen) {\n await this.closeBrowser();\n }\n }\n }\n\n /**\n * Explicitly close the browser instance\n */\n async closeBrowser(): Promise<void> {\n if (this.isBrowserOpen) {\n this.logger.info('Closing browser');\n await this.browser.close();\n this.isBrowserOpen = false;\n }\n }\n\n private async search(\n browser: BrowserInterface,\n options: {\n query: string;\n count?: number;\n needVisitedUrls?: boolean;\n excludeDomains: string[];\n queue: PromiseQueue;\n visitedUrls: Set<string>;\n truncate?: number;\n engine: LocalBrowserSearchEngine;\n },\n ) {\n const searchEngine = getSearchEngine(options.engine);\n const url = searchEngine.getSearchUrl(options.query, {\n count: options.count,\n excludeDomains: options.excludeDomains,\n });\n\n this.logger.info(`Searching with ${options.engine} engine: ${url}`);\n\n let links = await browser.evaluateOnNewPage({\n url,\n waitForOptions: {\n waitUntil: 'networkidle0',\n },\n pageFunction: searchEngine.extractSearchResults,\n pageFunctionParams: [],\n beforePageLoad: async (page) => {\n await interceptRequest(page);\n },\n afterPageLoad: async (page) => {\n // const content = await page.screenshot({\n // type: 'jpeg',\n // quality: 50,\n // encoding: 'base64',\n // });\n // this.logger.info('Page content:', content);\n if (searchEngine.waitForSearchResults)\n await searchEngine.waitForSearchResults(page, 10000);\n },\n });\n\n this.logger.info(`Fetched ${links?.length ?? 0} links`);\n\n // Filter links\n links =\n links?.filter((link) => {\n if (options.visitedUrls.has(link.url)) return false;\n options.visitedUrls.add(link.url);\n return !shouldSkipDomain(link.url);\n }) || [];\n\n if (!links.length) {\n this.logger.info('No valid links found');\n return [];\n }\n\n // Visit each link and extract content\n const results = await Promise.allSettled(\n options.needVisitedUrls\n ? links.map((item) =>\n options.queue.add(() => this.visitLink(this.browser, item)),\n )\n : links,\n );\n\n return results\n .map((result) => {\n if (result.status === 'rejected' || !result.value) return null;\n\n return {\n ...result.value,\n content: options.truncate\n ? result.value.content.slice(0, options.truncate)\n : result.value.content,\n };\n }).filter((v): v is SearchResult => v !== null);\n }\n\n private async visitLink(\n browser: BrowserInterface,\n item: SearchResult,\n ): Promise<SearchResult | undefined> {\n try {\n this.logger.info('Visiting link:', item.url);\n\n const result = await browser.evaluateOnNewPage({\n url: item.url,\n pageFunction: extractPageInformation,\n pageFunctionParams: [READABILITY_SCRIPT],\n beforePageLoad: async (page) => {\n await interceptRequest(page);\n },\n });\n\n if (result) {\n const content = toMarkdown(result.content);\n return { ...result, url: item.url, content, snippet: item.snippet };\n }\n } catch (e) {\n this.logger.error('Failed to visit link:', e);\n }\n }\n}\n\ndeclare global {\n interface Window {\n Readability: any;\n }\n}\n","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/search/browser-search\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport Turndown from 'turndown';\nimport { gfm } from 'turndown-plugin-gfm';\nimport { defaultLogger as logger } from '@agent-infra/logger';\nimport { Page } from '../browser/index.js';\nimport UserAgent from 'user-agents';\n\n/**\n * Safely parses a URL string into a URL object\n * @param url - The URL string to parse\n * @returns URL object or null if invalid\n */\nconst parseUrl = (url: string) => {\n try {\n return new URL(url);\n } catch {\n return null;\n }\n};\n\n/**\n * Determines if a domain should be skipped based on a blocklist\n * @param url - The URL to check\n * @returns True if the domain should be skipped, false otherwise\n */\nexport const shouldSkipDomain = (url: string) => {\n const parsed = parseUrl(url);\n if (!parsed) return true;\n\n const { hostname } = parsed;\n return [\n 'reddit.com',\n 'www.reddit.com',\n 'x.com',\n 'twitter.com',\n 'www.twitter.com',\n 'youtube.com',\n 'www.youtube.com',\n ].includes(hostname);\n};\n\n/**\n * Applies various stealth techniques to make the browser appear more like a regular user browser\n * @param page - Puppeteer page object\n */\nexport async function applyStealthScripts(page: Page) {\n const userAgent = new UserAgent({\n deviceCategory: 'desktop',\n }).toString();\n await page.setBypassCSP(true);\n await page.setUserAgent(userAgent);\n\n /**\n * https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html\n */\n await page.evaluate(() => {\n /**\n * Override the navigator.webdriver property\n * The webdriver read-only property of the navigator interface indicates whether the user agent is controlled by automation.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver\n */\n Object.defineProperty(navigator, 'webdriver', {\n get: () => undefined,\n });\n\n // Mock languages and plugins to mimic a real browser\n Object.defineProperty(navigator, 'languages', {\n get: () => ['en-US', 'en'],\n });\n\n Object.defineProperty(navigator, 'plugins', {\n get: () => [{}, {}, {}, {}, {}],\n });\n\n // Redefine the headless property\n Object.defineProperty(navigator, 'headless', {\n get: () => false,\n });\n\n // Override the permissions API\n const originalQuery = window.navigator.permissions.query;\n window.navigator.permissions.query = (parameters) =>\n parameters.name === 'notifications'\n ? Promise.resolve({\n state: Notification.permission,\n } as PermissionStatus)\n : originalQuery(parameters);\n });\n}\n\n/**\n * Sets up request interception to block unnecessary resources and apply stealth techniques\n * @param page - Puppeteer page object\n */\nexport async function interceptRequest(page: Page) {\n await applyStealthScripts(page);\n await page.setRequestInterception(true);\n\n page.on('request', (request) => {\n const resourceType = request.resourceType();\n\n if (resourceType !== 'document') {\n return request.abort();\n }\n\n if (request.isNavigationRequest()) {\n return request.continue();\n }\n\n return request.abort();\n });\n}\n\n/**\n * Interface representing extracted page information\n */\ninterface PageInfo {\n /** Page title */\n title: string;\n /** Page content in HTML format */\n content: string;\n}\n\n/**\n * !NOTE: This function runs in the context of the browser page, not Node.js\n * \n * Extracts readable content from a web page using Readability\n * @param window Browser window object\n * @param readabilityScript Readability library script as string\n * @returns Extracted page information (title and content)\n */\nexport function extractPageInformation(\n window: Window,\n readabilityScript: string,\n): PageInfo {\n const Readability = new Function(\n 'module',\n `${readabilityScript}\\nreturn module.exports`,\n )({});\n\n const document = window.document;\n\n // Remove non-content elements to improve extraction quality\n document\n .querySelectorAll(\n 'script,noscript,style,link,svg,img,video,iframe,canvas,.reflist',\n )\n .forEach((el) => el.remove());\n\n // Parse the document using Readability\n const article = new Readability(document).parse();\n const content = article?.content || '';\n const title = document.title;\n\n return {\n content,\n title: article?.title || title,\n };\n}\n\nexport interface ToMarkdownOptions extends Turndown.Options {\n gfmExtension?: boolean;\n}\n\n/**\n * Convert HTML content to Markdown format\n * @param html HTML string\n * @param options Conversion options\n * @returns Markdown string\n */\nexport function toMarkdown(\n html: string,\n options: ToMarkdownOptions = {},\n): string {\n if (!html) return '';\n\n try {\n const {\n codeBlockStyle = 'fenced',\n headingStyle = 'atx',\n emDelimiter = '*',\n strongDelimiter = '**',\n gfmExtension = true,\n } = options;\n\n const turndown = new Turndown({\n codeBlockStyle,\n headingStyle,\n emDelimiter,\n strongDelimiter,\n });\n\n if (gfmExtension) {\n turndown.use(gfm);\n }\n\n return turndown.turndown(html);\n } catch (error) {\n logger.error('Error converting HTML to Markdown:', error);\n return html;\n }\n}\n","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport interface Task<T> {\n (): Promise<T>;\n}\n\nexport class PromiseQueue {\n private queue: Task<any>[] = [];\n\n private concurrency: number;\n\n private running = 0;\n\n private results: any[] = [];\n\n constructor(concurrency = 1) {\n this.concurrency = concurrency;\n }\n\n add<T>(task: Task<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n this.queue.push(async () => {\n try {\n const result = await task();\n resolve(result);\n return result;\n } catch (error) {\n reject(error);\n throw error;\n }\n });\n this.run();\n });\n }\n\n private async run() {\n if (this.running >= this.concurrency || this.queue.length === 0) {\n return;\n }\n\n this.running++;\n const task = this.queue.shift()!;\n\n try {\n const result = await task();\n this.results.push(result);\n } catch (error) {\n // Handle error if needed\n } finally {\n this.running--;\n this.run();\n }\n }\n\n async waitAll(): Promise<any[]> {\n while (this.running > 0 || this.queue.length > 0) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n return this.results;\n }\n}","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Page } from 'puppeteer-core';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Bing search engine adapter implementation.\n * Provides functionality to generate Bing search URLs and extract search results from Bing search pages.\n */\nexport class BingSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Bing search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Bing search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const searchParams = new URLSearchParams({\n q: `${\n options.excludeDomains && options.excludeDomains.length > 0\n ? `${options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')} `\n : ''\n }${query}`,\n count: `${options.count || 10}`,\n });\n\n return `https://www.bing.com/search?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Bing search page.\n *\n * @param window - The browser window object containing the loaded Bing search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n /**\n * Validates if a string is a properly formatted URL.\n *\n * @param url - The URL string to validate\n * @returns Boolean indicating if the URL is valid\n */\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n /**\n * Extracts the snippet text from a search result element\n * @param element - The search result element\n * @returns The extracted snippet text\n */\n const extractSnippet = (element: Element): string => {\n // Clone the element to avoid modifying the original DOM\n const clone = element.cloneNode(true) as Element;\n \n // Remove title elements (typically h2 tags in Bing)\n const titleElements = clone.querySelectorAll('h2');\n titleElements.forEach((el) => el.remove());\n\n // Remove any cite/URL elements\n const citeElements = clone.querySelectorAll('.b_attribution');\n citeElements.forEach((el) => el.remove());\n\n // Remove script and style elements\n const scriptElements = clone.querySelectorAll('script, style');\n scriptElements.forEach((el) => el.remove());\n\n // Get text content and remove duplicates\n const text = Array.from(clone.querySelectorAll('*'))\n .filter((node) => node.textContent?.trim())\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .reduce((acc: string[], curr) => {\n // Only add text if it's not already included in accumulated text\n if (\n !acc.some(\n (text) =>\n text.includes(curr as string) ||\n (curr as string).includes(text),\n )\n ) {\n acc.push(curr as string);\n }\n return acc;\n }, [])\n .join(' ')\n .trim()\n .replace(/\\s+/g, ' ');\n\n return text;\n };\n\n try {\n // Bing search results are in elements with class 'b_algo'\n const elements = document.querySelectorAll('.b_algo');\n elements.forEach((element) => {\n const titleEl = element.querySelector('h2');\n const urlEl = element.querySelector('h2 a');\n const url = urlEl?.getAttribute('href');\n const snippet = extractSnippet(element);\n\n if (!url || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n snippet,\n url,\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error('Error extracting search results from Bing:', error);\n throw error;\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#b_results', {\n timeout: timeout ?? 10000,\n });\n }\n}","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { Page } from '../../browser/index.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Baidu search engine adapter implementation.\n * Provides functionality to generate Baidu search URLs and extract search results from Baidu search pages.\n */\nexport class BaiduSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Baidu search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Baidu search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n // Baidu doesn't support excluding domains in the same way as Google\n // But we can add '-site:domain' to the query\n const excludeDomainsQuery =\n options.excludeDomains && options.excludeDomains.length > 0\n ? options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')\n : '';\n\n const searchParams = new URLSearchParams({\n wd: excludeDomainsQuery ? `${excludeDomainsQuery} ${query}` : query,\n rn: `${options.count || 10}`, // rn is the parameter for result count\n });\n\n return `https://www.baidu.com/s?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Baidu search page.\n *\n * @param window - The browser window object containing the loaded Baidu search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n try {\n // Baidu search results are in elements with class 'result'\n const elements = document.querySelectorAll('.result');\n elements.forEach((element) => {\n const titleEl = element.querySelector('.t a');\n const url = titleEl?.getAttribute('href');\n const snippetEl = element.querySelector('.c-span-last .content-right_2s-H4');\n\n if (!url) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n url, // Note: Baidu uses redirects, we'll need to follow them\n snippet: snippetEl?.textContent || '',\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error('Error extracting search results from Baidu:', error);\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#page', {\n timeout: timeout ?? 10000,\n });\n }\n}","import { Page } from '../../browser/index.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\nexport class SogouSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Sogou search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Sogou search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const { count = 10, excludeDomains = [] } = options;\n\n const excludeDomainsQuery =\n excludeDomains && excludeDomains.length > 0\n ? excludeDomains.map((domain) => `-site:${domain}`).join(' ')\n : '';\n\n const searchParams = new URLSearchParams({\n query: `${excludeDomainsQuery ? `${excludeDomainsQuery} ` : ''}${query}`,\n num: `${count}`,\n });\n\n return `https://www.sogou.com/web?${searchParams.toString()}`;\n }\n\n /**\n * !NOTE: This function runs in the context of the browser page, not Node.js\n * \n * Extract search results from Sogou\n * @param window - The window object\n * @returns Search results\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n const EndPoints = 'https://www.sogou.com';\n \n const SELECTOR = {\n results: '.results .vrwrap',\n resultTitle: '.vr-title',\n resultLink: '.vr-title > a',\n resultSnippet: ['.star-wiki', '.fz-mid', '.attribute-centent'],\n resultSnippetExcluded: ['.text-lightgray', '.zan-box', '.tag-website'],\n related: '#main .vrwrap.middle-better-hintBox .hint-mid',\n };\n\n try {\n const elements = document.querySelectorAll(SELECTOR.results);\n elements.forEach((element) => {\n const titleEl = element.querySelector(SELECTOR.resultTitle);\n let url = element.querySelector(SELECTOR.resultLink)?.getAttribute('href');\n\n const snippets = SELECTOR.resultSnippet.map((selector) => {\n // remove excluded elements\n SELECTOR.resultSnippetExcluded.forEach((excludedSelector) => {\n const el = element.querySelector(excludedSelector);\n el?.remove();\n });\n // get the text content of the element\n const el = element.querySelector(selector);\n return el?.textContent?.trim() || '';\n });\n\n if (!url?.includes('http')) url = `${EndPoints}${url}`;\n\n if (!url?.trim() || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent?.trim() || '',\n url,\n snippet: snippets.join(''),\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error('Error extracting search results from Sogou:', msg);\n throw error;\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#pagebar_container', {\n timeout: timeout ?? 10000,\n });\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Page } from '../../browser/types.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Google search engine adapter implementation.\n * Provides functionality to generate Google search URLs and extract search results from Google search pages.\n */\nexport class GoogleSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Google search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Google search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const searchParams = new URLSearchParams({\n q: `${\n options.excludeDomains && options.excludeDomains.length > 0\n ? `${options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')} `\n : ''\n }${query}`,\n num: `${options.count || 10}`,\n });\n\n searchParams.set('udm', '14');\n return `https://www.google.com/search?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Google search page.\n *\n * @param window - The browser window object containing the loaded Google search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n /**\n * Validates if a string is a properly formatted URL.\n *\n * @param url - The URL string to validate\n * @returns Boolean indicating if the URL is valid\n */\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n /**\n * Extracts the snippet text from an element by cloning it and removing title elements\n *\n * @param element - The search result element\n * @returns The extracted snippet text\n */\n const extractSnippet = (element: Element): string => {\n // Clone the element to avoid modifying the original DOM\n const clone = element.cloneNode(true) as Element;\n\n // Remove title elements (typically h3 tags in Google)\n const titleElements = clone.querySelectorAll('h3');\n titleElements.forEach((el) => el.remove());\n\n // Remove any cite elements (showing the URL)\n const citeElements = clone.querySelectorAll('cite');\n citeElements.forEach((el) => el.remove());\n\n // Remove script and style elements\n const scriptElements = clone.querySelectorAll('script, style');\n scriptElements.forEach((el) => el.remove());\n\n // Get text content and remove duplicates\n const text = Array.from(clone.querySelectorAll('*'))\n .filter((node) => node.textContent?.trim())\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .reduce((acc: string[], curr) => {\n // Only add text if it's not already included in accumulated text\n if (\n !acc.some(\n (text) =>\n text.includes(curr as string) ||\n (curr as string).includes(text),\n )\n ) {\n acc.push(curr as string);\n }\n return acc;\n }, [])\n .join(' ')\n .trim()\n .replace(/\\s+/g, ' ');\n\n return text;\n };\n\n try {\n // Google search results are contained in elements with class 'tF2Cxc'\n // It may change at any time\n const elements = document.querySelectorAll('.tF2Cxc');\n elements.forEach((element) => {\n const titleEl = element.querySelector('h3');\n const urlEl = element.querySelector('a');\n const url = urlEl?.getAttribute('href');\n\n // Extract snippet using the generic method\n const snippet = extractSnippet(element.parentElement || element);\n\n if (!url || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n url,\n snippet,\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error(error);\n }\n\n return links;\n }\n\n /**\n * Waits for Google search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#search', {\n timeout: timeout ?? 10000,\n });\n }\n}","import { BingSearchEngine } from './bing.js';\nimport { BaiduSearchEngine } from './baidu.js';\nimport type { LocalBrowserSearchEngine, SearchEngineAdapter } from '../types.js';\nimport { SogouSearchEngine } from './sogou.js';\nimport { GoogleSearchEngine } from './google.js';\n\n/**\n * Factory function to get the appropriate search engine adapter instance.\n *\n * @param engine - The search engine identifier ('sogou', 'bing', or 'baidu')\n * @returns An instance of the requested search engine adapter\n */\nexport function getSearchEngine(engine: LocalBrowserSearchEngine): SearchEngineAdapter {\n switch (engine) {\n case 'bing':\n return new BingSearchEngine();\n case 'baidu':\n return new BaiduSearchEngine();\n case 'sogou':\n return new SogouSearchEngine();\n case 'google':\n return new GoogleSearchEngine();\n default:\n return new BingSearchEngine();\n }\n}","import { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from '../interface.js';\nimport { BrowserSearch, LocalBrowserSearchEngine } from '../libs/browser-search/index.js';\nimport { ConsoleLogger } from '@agent-infra/logger';\n\nconst logger = new ConsoleLogger('[LocalSearch]');\n\nexport async function localSearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const { query, limit = 10 } = options;\n let { engines = 'all' } = options;\n const browserSearch = new BrowserSearch({\n logger,\n browserOptions: {\n headless: true,\n },\n });\n\n if (engines === 'all') {\n engines = 'bing,google,baidu,sogou';\n }\n\n try {\n const engineList = engines.split(',');\n\n if (engineList.length === 0) {\n throw new Error('engines is required');\n }\n\n const results: ISearchResponseResult[] = [];\n\n for (const engine of engineList) {\n const res = await browserSearch.perform({\n query,\n count: limit,\n engine: engine as LocalBrowserSearchEngine,\n needVisitedUrls: false,\n });\n\n if (res.length > 0) {\n results.push(...res);\n break;\n }\n }\n\n logger.info(`Found ${results.length} results for ${query}`, results);\n\n return {\n results,\n success: true,\n };\n } finally {\n await browserSearch.closeBrowser();\n }\n}","/**\n * The following tools are based on the Firecrawl MCP Server\n * https://github.com/mendableai/firecrawl-mcp-server\n */\n\nimport { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n// tools definition\nexport const SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n enum: [\n 'general',\n 'news',\n 'images',\n 'videos',\n 'it',\n 'science',\n 'map',\n 'music',\n 'files',\n 'social_media',\n ],\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n enum: [\n 'all',\n 'day',\n 'week',\n 'month',\n 'year',\n ],\n },\n },\n required: ['query'],\n },\n};\n\nexport const MAP_TOOL: Tool = {\n name: 'one_map',\n description:\n 'Discover URLs from a starting point. Can use both sitemap.xml and HTML link discovery.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'Starting URL for URL discovery',\n },\n search: {\n type: 'string',\n description: 'Optional search term to filter URLs',\n },\n ignoreSitemap: {\n type: 'boolean',\n description: 'Skip sitemap.xml discovery and only use HTML links',\n },\n sitemapOnly: {\n type: 'boolean',\n description: 'Only use sitemap.xml for discovery, ignore HTML links',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include URLs from subdomains in results',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of URLs to return',\n },\n },\n required: ['url'],\n },\n};\n\nexport const SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\n\n\nexport const EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n"],"mappings":"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","names":["asyncRetry","url","logger","import_logger","url","puppeteer","import_logger","import_logger","url","UserAgent","window","document","Turndown","logger","window","document","url","text","window","document","url","window","document","url","el","window","document","url","text","url","import_logger","logger","dotenvx","FirecrawlApp","startTime","url"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/search/bing.ts","../src/search/duckduckgo.ts","../src/search/searxng.ts","../src/search/tavily.ts","../src/libs/browser/types.ts","../src/libs/browser/finder.ts","../src/libs/browser/base.ts","../src/libs/browser/local.ts","../src/libs/browser/remote.ts","../src/libs/browser-search/readability.ts","../src/libs/browser-search/search.ts","../src/libs/browser-search/utils.ts","../src/libs/browser-search/queue.ts","../src/libs/browser-search/engines/bing.ts","../src/libs/browser-search/engines/baidu.ts","../src/libs/browser-search/engines/sogou.ts","../src/libs/browser-search/engines/google.ts","../src/libs/browser-search/engines/get.ts","../src/search/local.ts","../src/tools.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { ISearchRequestOptions, ISearchResponse, SearchProvider } from './interface.js';\nimport { bingSearch, duckDuckGoSearch, searxngSearch, tavilySearch, localSearch } from './search/index.js';\nimport { SEARCH_TOOL, EXTRACT_TOOL, SCRAPE_TOOL, MAP_TOOL } from './tools.js';\nimport FirecrawlApp, { MapParams, ScrapeParams } from '@mendable/firecrawl-js';\nimport dotenvx from '@dotenvx/dotenvx';\nimport { SafeSearchType } from 'duck-duck-scrape';\n\ndotenvx.config();\n\n// search api\nconst SEARCH_API_URL = process.env.SEARCH_API_URL;\nconst SEARCH_API_KEY = process.env.SEARCH_API_KEY;\nconst SEARCH_PROVIDER: SearchProvider = process.env.SEARCH_PROVIDER as SearchProvider ?? 'local';\n\n// search query params\nconst SAFE_SEARCH = process.env.SAFE_SEARCH ?? 0;\nconst LIMIT = process.env.LIMIT ?? 10;\nconst CATEGORIES = process.env.CATEGORIES ?? 'general';\nconst ENGINES = process.env.ENGINES ?? 'all';\nconst FORMAT = process.env.FORMAT ?? 'json';\nconst LANGUAGE = process.env.LANGUAGE ?? 'auto';\nconst TIME_RANGE = process.env.TIME_RANGE ?? '';\nconst DEFAULT_TIMEOUT = process.env.TIMEOUT ?? 10000;\n\n// firecrawl api\nconst FIRECRAWL_API_KEY = process.env.FIRECRAWL_API_KEY;\nconst FIRECRAWL_API_URL = process.env.FIRECRAWL_API_URL;\n\n// firecrawl client\nconst firecrawl = new FirecrawlApp({\n apiKey: FIRECRAWL_API_KEY ?? '',\n ...(FIRECRAWL_API_URL ? { apiUrl: FIRECRAWL_API_URL } : {}),\n});\n\n// Server implementation\nconst server = new Server(\n {\n name: 'one-search-mcp',\n version: '0.0.1',\n },\n {\n capabilities: {\n tools: {},\n logging: {},\n },\n },\n);\n\nconst searchDefaultConfig = {\n limit: Number(LIMIT),\n categories: CATEGORIES,\n format: FORMAT,\n safesearch: SAFE_SEARCH,\n language: LANGUAGE,\n engines: ENGINES,\n time_range: TIME_RANGE,\n timeout: DEFAULT_TIMEOUT,\n};\n\n// Tool handlers\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: [\n SEARCH_TOOL,\n EXTRACT_TOOL,\n SCRAPE_TOOL,\n MAP_TOOL,\n ],\n}));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const startTime = Date.now();\n\n try {\n const { name, arguments: args } = request.params;\n\n if (!args) {\n throw new Error('No arguments provided');\n }\n \n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Received request for tool: [${name}]`,\n });\n \n switch (name) {\n case 'one_search': {\n // check args.\n if (!checkSearchArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { results, success } = await processSearch({\n ...args,\n apiKey: SEARCH_API_KEY ?? '',\n apiUrl: SEARCH_API_URL,\n });\n if (!success) {\n throw new Error('Failed to search');\n }\n const resultsText = results.map((result) => (\n `Title: ${result.title}\nURL: ${result.url}\nDescription: ${result.snippet}\n${result.markdown ? `Content: ${result.markdown}` : ''}`\n ));\n return {\n content: [\n {\n type: 'text',\n text: resultsText.join('\\n\\n'),\n },\n ],\n results,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error searching: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_scrape': {\n if (!checkScrapeArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const startTime = Date.now();\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping started for url: [${args.url}]`,\n });\n\n const { url, ...scrapeArgs } = args;\n const { content, success, result } = await processScrape(url, scrapeArgs);\n\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Scraping completed in ${Date.now() - startTime}ms`,\n });\n\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error scraping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : 'Unknown error';\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n case 'one_map': {\n if (!checkMapArgs(args)) {\n throw new Error(`Invalid arguments for tool: [${name}]`);\n }\n try {\n const { content, success, result } = await processMapUrl(args.url, args);\n return {\n content,\n result,\n success,\n };\n } catch (error) {\n server.sendLoggingMessage({\n level: 'error',\n data: `[${new Date().toISOString()}] Error mapping: ${error}`,\n });\n const msg = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n }\n }\n default: {\n throw new Error(`Unknown tool: ${name}`);\n }\n }\n } catch(error) {\n const msg = error instanceof Error ? error.message : String(error);\n server.sendLoggingMessage({\n level: 'error',\n data: {\n message: `[${new Date().toISOString()}] Error processing request: ${msg}`,\n tool: request.params.name,\n arguments: request.params.arguments,\n timestamp: new Date().toISOString(),\n duration: Date.now() - startTime,\n },\n });\n return {\n success: false,\n content: [\n {\n type: 'text',\n text: msg,\n },\n ],\n };\n } finally {\n server.sendLoggingMessage({\n level: 'info',\n data: `[${new Date().toISOString()}] Request completed in ${Date.now() - startTime}ms`,\n });\n }\n});\n\nasync function processSearch(args: ISearchRequestOptions): Promise<ISearchResponse> {\n switch (SEARCH_PROVIDER) {\n case 'searxng': {\n // merge default config with args\n const params = {\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n };\n\n // but categories and language have higher priority (ENV > args).\n const { categories, language } = searchDefaultConfig;\n\n if (categories) {\n params.categories = categories;\n }\n if (language) {\n params.language = language;\n }\n return await searxngSearch(params);\n }\n case 'tavily': {\n return await tavilySearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n }\n case 'bing': {\n return await bingSearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n });\n }\n case 'duckduckgo': {\n const safeSearch = args.safeSearch ?? 0;\n const safeSearchOptions = [SafeSearchType.STRICT, SafeSearchType.MODERATE, SafeSearchType.OFF];\n return await duckDuckGoSearch({\n ...searchDefaultConfig,\n ...args,\n apiKey: SEARCH_API_KEY,\n safeSearch: safeSearchOptions[safeSearch],\n });\n }\n case 'local': {\n return await localSearch({\n ...searchDefaultConfig,\n ...args,\n });\n }\n default:\n throw new Error(`Unsupported search provider: ${SEARCH_PROVIDER}`);\n }\n}\n\nasync function processScrape(url: string, args: ScrapeParams) {\n const res = await firecrawl.scrapeUrl(url, {\n ...args,\n });\n\n if (!res.success) {\n throw new Error(`Failed to scrape: ${res.error}`);\n }\n\n const content: string[] = [];\n\n if (res.markdown) {\n content.push(res.markdown);\n }\n\n if (res.rawHtml) {\n content.push(res.rawHtml);\n }\n\n if (res.links) {\n content.push(res.links.join('\\n'));\n }\n\n if (res.screenshot) {\n content.push(res.screenshot);\n }\n\n if (res.html) {\n content.push(res.html);\n }\n\n if (res.extract) {\n content.push(res.extract);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: content.join('\\n\\n') || 'No content found',\n },\n ],\n result: res,\n success: true,\n };\n}\n\nasync function processMapUrl(url: string, args: MapParams) {\n const res = await firecrawl.mapUrl(url, {\n ...args,\n });\n\n if ('error' in res) {\n throw new Error(`Failed to map: ${res.error}`);\n }\n\n if (!res.links) {\n throw new Error(`No links found from: ${url}`);\n }\n\n return {\n content: [\n {\n type: 'text',\n text: res.links.join('\\n').trim(),\n },\n ],\n result: res.links,\n success: true,\n };\n}\n\nfunction checkSearchArgs(args: unknown): args is ISearchRequestOptions {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'query' in args &&\n typeof args.query === 'string'\n );\n}\n\nfunction checkScrapeArgs(args: unknown): args is ScrapeParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nfunction checkMapArgs(args: unknown): args is MapParams & { url: string } {\n return (\n typeof args === 'object' &&\n args !== null &&\n 'url' in args &&\n typeof args.url === 'string'\n );\n}\n\nasync function runServer() {\n try {\n process.stdout.write('Starting OneSearch MCP server...\\n');\n\n const transport = new StdioServerTransport();\n await server.connect(transport);\n\n server.sendLoggingMessage({\n level: 'info',\n data: 'OneSearch MCP server started',\n });\n\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error starting server: ${msg}\\n`);\n process.exit(1);\n }\n}\n\n// run server\nrunServer().catch((error) => {\n const msg = error instanceof Error ? error.message : String(error);\n process.stderr.write(`Error running server: ${msg}\\n`);\n process.exit(1);\n});\n\n// export types\nexport * from './interface.js';\n","/**\n * Bing Search API\n */\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n\n/**\n * Options for performing a Bing search\n */\nexport interface BingSearchOptions {\n /**\n * Search query string\n */\n q: string;\n\n /**\n * Number of results to return\n */\n count?: number;\n\n /**\n * Result offset for pagination\n */\n offset?: number;\n\n /**\n * Market code (e.g., 'en-US')\n */\n mkt?: string;\n\n /**\n * Safe search filtering level\n */\n safeSearch?: 'Off' | 'Moderate' | 'Strict';\n\n /**\n * Bing API key\n */\n apiKey: string;\n\n /**\n * Bing Search API URL\n */\n apiUrl?: string;\n\n /**\n * Additional parameters supported by Bing Search API\n */\n [key: string]: any;\n}\n\n/**\n * Represents a web page result from Bing Search\n */\nexport interface BingSearchWebPage {\n /**\n * Title of the web page\n */\n name: string;\n\n /**\n * URL of the web page\n */\n url: string;\n\n /**\n * Text snippet from the web page\n */\n snippet: string;\n\n /**\n * Date the page was last crawled by Bing\n */\n dateLastCrawled?: string;\n\n /**\n * Display URL for the web page\n */\n displayUrl?: string;\n\n /**\n * Unique identifier for the result\n */\n id?: string;\n\n /**\n * Indicates if the content is family friendly\n */\n isFamilyFriendly?: boolean;\n\n /**\n * Indicates if the result is navigational\n */\n isNavigational?: boolean;\n\n /**\n * Language of the web page\n */\n language?: string;\n\n /**\n * Indicates if caching should be disabled\n */\n noCache?: boolean;\n\n /**\n * Name of the website\n */\n siteName?: string;\n\n /**\n * URL to a thumbnail image\n */\n thumbnailUrl?: string;\n}\n\n/**\n * Represents an image result from Bing Search\n */\nexport interface BingSearchImage {\n contentSize: string;\n contentUrl: string;\n datePublished: string;\n encodingFormat: string;\n height: number;\n width: number;\n hostPageDisplayUrl: string;\n hostPageUrl: string;\n name: string;\n thumbnail: {\n height: number;\n width: number;\n };\n thumbnailUrl: string;\n webSearchUrl: string;\n}\n\n/**\n * Represents a video result from Bing Search\n */\nexport interface BingSearchVideo {\n allowHttpsEmbed: boolean;\n allowMobileEmbed: boolean;\n contentUrl: string;\n creator?: {\n name: string;\n };\n datePublished: string;\n description: string;\n duration: string;\n embedHtml: string;\n encodingFormat: string;\n height: number;\n width: number;\n hostPageDisplayUrl: string;\n hostPageUrl: string;\n name: string;\n publisher?: {\n name: string;\n }[];\n thumbnail: {\n height: number;\n width: number;\n };\n thumbnailUrl: string;\n viewCount?: number;\n webSearchUrl: string;\n}\n\nexport interface BingSearchResponse {\n _type?: string;\n queryContext?: {\n originalQuery: string;\n };\n webPages?: {\n value: BingSearchWebPage[];\n totalEstimatedMatches?: number;\n someResultsRemoved?: boolean;\n webSearchUrl?: string;\n };\n images?: {\n value: BingSearchImage[];\n isFamilyFriendly?: boolean;\n readLink?: string;\n webSearchUrl?: string;\n id?: string;\n };\n videos?: {\n value: BingSearchVideo[];\n isFamilyFriendly?: boolean;\n readLink?: string;\n webSearchUrl?: string;\n id?: string;\n scenario?: string;\n };\n rankingResponse?: {\n mainline?: {\n items: {\n answerType: string;\n resultIndex?: number;\n value: {\n id: string;\n };\n }[];\n };\n };\n [key: string]: any; // Allow other response fields\n}\n\nexport async function bingSearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const { query, limit = 10, safeSearch = 0, page = 1, apiUrl = 'https://api.bing.microsoft.com/v7.0/search', apiKey, language } = options;\n\n const bingSafeSearchOptions = ['Off', 'Moderate', 'Strict'];\n\n if (!apiKey) {\n throw new Error('Bing API key is required');\n }\n\n const searchOptions = {\n q: query,\n count: limit,\n offset: (page - 1) * limit,\n mkt: language,\n safeSearch: bingSafeSearchOptions[safeSearch] as 'Off' | 'Moderate' | 'Strict',\n };\n\n try {\n const queryParams = new URLSearchParams();\n Object.entries(searchOptions).forEach(([key, value]) => {\n if (value !== undefined) {\n queryParams.set(key, value.toString());\n }\n });\n\n const res = await fetch(`${apiUrl}?${queryParams}`, {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n 'Ocp-Apim-Subscription-Key': apiKey,\n },\n });\n\n if (!res.ok) {\n throw new Error(`Bing search error: ${res.status} ${res.statusText}`);\n }\n\n const data = await res.json();\n const serp = data.webPages?.value as Array<BingSearchWebPage>;\n const results = serp?.map((item: BingSearchWebPage) => ({\n title: item.name,\n snippet: item.snippet,\n url: item.url,\n source: item.siteName,\n thumbnailUrl: item.thumbnailUrl,\n language: item.language,\n image: null,\n video: null,\n engine: 'bing',\n })) ?? [];\n\n return {\n results,\n success: true,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Bing search error.';\n process.stdout.write(msg);\n throw err;\n }\n}","import * as DDG from 'duck-duck-scrape';\nimport asyncRetry from 'async-retry';\nimport type { SearchOptions } from 'duck-duck-scrape';\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n\nexport async function duckDuckGoSearch(options: Omit<ISearchRequestOptions, 'safeSearch'> & SearchOptions): Promise<ISearchResponse> {\n try {\n const { query, timeout = 10000, safeSearch = DDG.SafeSearchType.OFF, retry = { retries: 3 }, ...searchOptions } = options;\n \n const res = await asyncRetry(\n () => {\n return DDG.search(query, {\n ...searchOptions,\n safeSearch,\n }, {\n // needle options\n response_timeout: timeout,\n });\n },\n retry,\n );\n\n const results = res ? {\n noResults: res.noResults,\n vqd: res.vqd,\n results: res.results,\n } : {\n noResults: true,\n vqd: '',\n results: [],\n };\n\n return {\n results: results.results.map((result) => ({\n title: result.title,\n snippet: result.description,\n url: result.url,\n source: result.hostname,\n image: null,\n video: null,\n engine: 'duckduckgo',\n })),\n success: true,\n };\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'DuckDuckGo search error.';\n process.stdout.write(msg);\n throw error;\n }\n}\n","import url from 'node:url';\nimport { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from '../interface.js';\n\n/**\n * SearxNG Search API\n * - https://docs.searxng.org/dev/search_api.html\n */\nexport async function searxngSearch(params: ISearchRequestOptions): Promise<ISearchResponse> {\n try {\n const {\n query,\n page = 1,\n limit = 10,\n categories = 'general',\n engines = 'all',\n safeSearch = 0,\n format = 'json',\n language = 'auto',\n timeRange = '',\n timeout = 10000,\n apiKey,\n apiUrl,\n } = params;\n\n if (!apiUrl) {\n throw new Error('SearxNG API URL is required');\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), Number(timeout));\n\n const config = {\n q: query,\n pageno: page,\n categories,\n format,\n safesearch: safeSearch,\n language,\n engines,\n time_range: timeRange,\n };\n\n const endpoint = `${apiUrl}/search`;\n\n const queryParams = url.format({ query: config });\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n const res = await fetch(`${endpoint}${queryParams}`, {\n method: 'POST',\n headers,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n const response = await res.json();\n if (response.results) {\n const list = (response.results as Array<Record<string, any>>).slice(0, limit);\n const results: ISearchResponseResult[] = list.map((item: Record<string, any>) => {\n const image = item.img_src ? {\n thumbnail: item.thumbnail_src,\n src: item.img_src,\n } : null;\n const video = item.iframe_src ? {\n thumbnail: item.thumbnail_src,\n src: item.iframe_src,\n } : null;\n return {\n title: item.title,\n snippet: item.content,\n url: item.url,\n source: item.source,\n image,\n video,\n engine: item.engine,\n };\n });\n return {\n results,\n success: true,\n };\n }\n return {\n results: [],\n success: false,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Searxng search error.';\n process.stdout.write(msg);\n throw err;\n }\n}\n","import { tavily, TavilySearchOptions } from '@tavily/core';\nimport { ISearchRequestOptions, ISearchResponse } from '../interface.js';\n\n/**\n * Tavily Search API\n * - https://docs.tavily.com/documentation/quickstart\n */\nexport async function tavilySearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const {\n query,\n limit = 10,\n categories = 'general',\n timeRange,\n apiKey,\n } = options;\n\n if (!apiKey) {\n throw new Error('Tavily API key is required');\n }\n\n try {\n const tvly = tavily({\n apiKey,\n });\n \n const params: TavilySearchOptions = {\n topic: categories as TavilySearchOptions['topic'],\n timeRange: timeRange as TavilySearchOptions['timeRange'],\n maxResults: limit,\n };\n \n const res = await tvly.search(query, params);\n const results = res.results.map(item => ({\n title: item.title,\n url: item.url,\n snippet: item.content,\n engine: 'tavily',\n }));\n \n return {\n results,\n success: true,\n };\n } catch (error) {\n const msg = error instanceof Error ? error.message : 'Tavily search error.';\n process.stdout.write(msg);\n throw error;\n }\n}","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/browser\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { Page, WaitForOptions } from 'puppeteer-core';\n\n/**\n * Options for launching a browser instance\n * @interface LaunchOptions\n */\nexport interface LaunchOptions {\n /**\n * Whether to run browser in headless mode\n * @default false\n */\n headless?: boolean;\n\n /**\n * Maximum time in milliseconds to wait for the browser to start\n * @default 0 (no timeout)\n */\n timeout?: number;\n\n /**\n * The viewport dimensions\n * @property {number} width - Viewport width in pixels\n * @property {number} height - Viewport height in pixels\n */\n defaultViewport?: {\n width: number;\n height: number;\n };\n\n /**\n * Path to a browser executable to use instead of the automatically detected one\n * If not provided, the system will attempt to find an installed browser\n */\n executablePath?: string;\n\n /**\n * Path to a specific browser profile to use\n * Allows using existing browser profiles with cookies, extensions, etc.\n */\n profilePath?: string;\n\n /**\n * Proxy server URL, e.g. 'http://proxy.example.com:8080'\n * Used to route browser traffic through a proxy server\n */\n proxy?: string;\n}\n\n/**\n * Options for evaluating JavaScript in a new page\n * @template T - Array of parameters to pass to the page function\n * @template R - Return type of the page function\n * @interface EvaluateOnNewPageOptions\n */\nexport interface EvaluateOnNewPageOptions<T extends any[], R> {\n /**\n * URL to navigate to before evaluating the function\n * The page will load this URL before executing the pageFunction\n */\n url: string;\n\n /**\n * Options for waiting for the page to load\n */\n waitForOptions?: WaitForOptions;\n\n /**\n * Function to be evaluated in the page context\n * This function runs in the context of the browser page, not Node.js\n * @param {Window} window - The window object of the page\n * @param {...T} args - Additional arguments passed to the function\n * @returns {R} Result of the function execution\n */\n pageFunction: (window: Window, ...args: T) => R;\n\n /**\n * Parameters to pass to the page function\n * These values will be serialized and passed to the pageFunction\n */\n pageFunctionParams: T;\n\n /**\n * Optional function to execute before page navigation\n * Useful for setting up page configuration before loading the URL\n * @param {Page} page - Puppeteer page instance\n * @returns {void | Promise<void>}\n */\n beforePageLoad?: (page: Page) => void | Promise<void>;\n\n /**\n * Optional function to execute after page navigation\n * Useful for setting up page configuration after loading the URL\n * @param {Page} page - Puppeteer page instance\n * @returns {void | Promise<void>}\n */\n afterPageLoad?: (page: Page) => void | Promise<void>;\n\n /**\n * Optional function to process the result before returning\n * Can be used to transform or validate the result from page evaluation\n * @param {Page} page - Puppeteer page instance\n * @param {R} result - Result from page function evaluation\n * @returns {R | Promise<R>} Processed result\n */\n beforeSendResult?: (page: Page, result: R) => R | Promise<R>;\n}\n\n/**\n * Core browser interface that all browser implementations must implement\n * Defines the standard API for browser automation\n * @interface BrowserInterface\n */\nexport interface BrowserInterface {\n /**\n * Launch a new browser instance\n * @param {LaunchOptions} [options] - Launch configuration options\n * @returns {Promise<void>} Promise resolving when browser is launched\n */\n launch(options?: LaunchOptions): Promise<void>;\n\n /**\n * Close the browser instance and all its pages\n * @returns {Promise<void>} Promise resolving when browser is closed\n */\n close(): Promise<void>;\n\n /**\n * Create a new page in the browser\n * @returns {Promise<Page>} Promise resolving to the new page instance\n */\n createPage(): Promise<Page>;\n\n /**\n * Evaluate a function in a new page context\n * Creates a new page, navigates to URL, executes function, and returns result\n * @template T - Array of parameters to pass to the page function\n * @template R - Return type of the page function\n * @param {EvaluateOnNewPageOptions<T, R>} options - Evaluation options\n * @returns {Promise<R | null>} Promise resolving to the function result or null\n */\n evaluateOnNewPage<T extends any[], R>(\n options: EvaluateOnNewPageOptions<T, R>,\n ): Promise<R | null>;\n\n /**\n * Get the currently active page or create one if none exists\n * @returns {Promise<Page>} Promise resolving to the active page instance\n */\n getActivePage(): Promise<Page>;\n}\n\nexport { Page };","/**\n * The following code is modified based on\n * https://github.com/egoist/local-web-search/blob/main/src/find-browser.ts\n * Copy from\n * https://github.com/bytedance/UI-TARS-desktop/blob/main/packages/agent-infra/browser/src/browser-finder.ts\n * \n * MIT Licensed\n * Copyright (c) 2025 ChatWise (https://chatwise.app) <kevin@chatwise.app>\n * https://github.com/egoist/local-web-search/blob/main/LICENSE\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as os from 'os';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\n\n/**\n * Interface defining browser locations and configurations\n * Contains paths and settings for different operating systems\n * @interface Browser\n */\ninterface Browser {\n /**\n * Browser name identifier\n */\n name: string;\n\n /**\n * Executable paths by platform\n * @property {string} win32 - Windows executable path\n * @property {string} darwin - macOS executable path\n * @property {string} linux - Linux executable path\n */\n executable: {\n win32: string;\n darwin: string;\n linux: string;\n };\n\n /**\n * User data directory paths by platform\n * @property {string} win32 - Windows user data directory\n * @property {string} darwin - macOS user data directory\n * @property {string} linux - Linux user data directory\n */\n userDataDir: {\n win32: string;\n darwin: string;\n linux: string;\n };\n}\n\n/**\n * Class responsible for finding and managing browser installations\n * Detects installed browsers and their profiles across different platforms\n */\nexport class BrowserFinder {\n /**\n * Logger instance for diagnostic output\n */\n private logger: Logger;\n\n /**\n * Creates a new BrowserFinder instance\n * @param {Logger} [logger] - Optional custom logger\n */\n constructor(logger?: Logger) {\n this.logger = logger ?? defaultLogger;\n }\n\n /**\n * Getter that returns the list of supported browsers with their platform-specific paths\n * @returns {Browser[]} Array of browser configurations\n * @private\n */\n private get browsers(): Browser[] {\n // Get HOME_DIR inside the getter to ensure it's always current\n const HOME_DIR = os.homedir();\n const LOCAL_APP_DATA = process.env.LOCALAPPDATA;\n\n return [\n {\n name: 'Chromium',\n executable: {\n win32: 'C:\\\\Program Files\\\\Chromium\\\\Application\\\\chrome.exe',\n darwin: '/Applications/Chromium.app/Contents/MacOS/Chromium',\n linux: '/usr/bin/chromium',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Chromium\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Chromium`,\n linux: `${HOME_DIR}/.config/chromium`,\n },\n },\n {\n name: 'Google Chrome',\n executable: {\n win32: 'C:\\\\Program Files\\\\Google\\\\Chrome\\\\Application\\\\chrome.exe',\n darwin:\n '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',\n linux: '/usr/bin/google-chrome',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Google\\\\Chrome\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Google/Chrome`,\n linux: `${HOME_DIR}/.config/google-chrome`,\n },\n },\n {\n name: 'Google Chrome Canary',\n executable: {\n win32:\n 'C:\\\\Program Files\\\\Google\\\\Chrome Canary\\\\Application\\\\chrome.exe',\n darwin:\n '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',\n linux: '/usr/bin/google-chrome-canary',\n },\n userDataDir: {\n win32: `${LOCAL_APP_DATA}\\\\Google\\\\Chrome Canary\\\\User Data`,\n darwin: `${HOME_DIR}/Library/Application Support/Google/Chrome Canary`,\n linux: `${HOME_DIR}/.config/google-chrome-canary`,\n },\n },\n ];\n }\n\n /**\n * Find a specific browser or the first available browser\n * @param {string} [name] - Optional browser name to find\n * @returns {{ executable: string; userDataDir: string }} Browser executable and user data paths\n * @throws {Error} If no supported browser is found or the platform is unsupported\n */\n findBrowser(name?: string): {\n executable: string;\n userDataDir: string;\n } {\n const platform = process.platform;\n this.logger.info('Finding browser on platform:', platform);\n\n if (platform !== 'darwin' && platform !== 'win32' && platform !== 'linux') {\n const error = new Error(`Unsupported platform: ${platform}`);\n this.logger.error(error.message);\n throw error;\n }\n\n const browser = name\n ? this.browsers.find(\n (b) => b.name === name && fs.existsSync(b.executable[platform]),\n )\n : this.browsers.find((b) => fs.existsSync(b.executable[platform]));\n\n this.logger.log('browser', browser);\n\n if (!browser) {\n const error = name\n ? new Error(`Cannot find browser: ${name}`)\n : new Error(\n 'Cannot find a supported browser on your system. Please install Chrome, Edge, or Brave.',\n );\n this.logger.error(error.message);\n throw error;\n }\n\n const result = {\n executable: browser.executable[platform],\n userDataDir: browser.userDataDir[platform],\n };\n\n this.logger.success(`Found browser: ${browser.name}`);\n this.logger.info('Browser details:', result);\n\n return result;\n }\n\n /**\n * Get browser profiles for a specific browser\n * Reads the Local State file to extract profile information\n * @param {string} [browserName] - Optional browser name to get profiles for\n * @returns {Array<{ displayName: string; path: string }>} Array of profile objects with display names and paths\n */\n getBrowserProfiles(\n browserName?: string,\n ): Array<{ displayName: string; path: string }> {\n const browser = this.findBrowser(browserName);\n\n try {\n const localState = JSON.parse(\n fs.readFileSync(path.join(browser.userDataDir, 'Local State'), 'utf8'),\n );\n const profileInfo = localState.profile.info_cache;\n\n return Object.entries(profileInfo).map(\n ([profileName, info]: [string, any]) => ({\n displayName: info.name,\n path: path.join(browser.userDataDir, profileName),\n }),\n );\n } catch (error) {\n return [];\n }\n }\n\n /**\n * Legacy method for backwards compatibility\n * Finds Chrome browser executable path\n * @deprecated Use findBrowser instead\n * @returns {string | null} Chrome executable path or null if not found\n */\n findChrome(): string | null {\n try {\n const { executable } = this.findBrowser('Google Chrome');\n return executable;\n } catch {\n return null;\n }\n }\n}\n","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/browser\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\nimport {\n BrowserInterface,\n EvaluateOnNewPageOptions,\n LaunchOptions,\n Page,\n} from './types.js';\n\n/**\n * Configuration options for the BaseBrowser class\n * @interface BaseBrowserOptions\n * @property {Logger} [logger] - Custom logger instance to use for browser logging\n */\nexport interface BaseBrowserOptions {\n logger?: Logger;\n}\n\n/**\n * Abstract base class that implements common browser automation functionality\n * Provides a foundation for specific browser implementations with shared capabilities\n * @abstract\n * @implements {BrowserInterface}\n */\nexport abstract class BaseBrowser implements BrowserInterface {\n /**\n * The underlying Puppeteer browser instance\n * @protected\n */\n protected browser: puppeteer.Browser | null = null;\n\n /**\n * Logger instance for browser-related logging\n * @protected\n */\n protected logger: Logger;\n\n /**\n * Reference to the currently active browser page\n * @protected\n */\n protected activePage: Page | null = null;\n\n /**\n * Creates an instance of BaseBrowser\n * @param {BaseBrowserOptions} [options] - Configuration options\n */\n constructor(options?: BaseBrowserOptions) {\n this.logger = options?.logger ?? defaultLogger;\n this.logger.info('Browser Options:', options);\n }\n\n /**\n * Get the underlying Puppeteer browser instance\n * @throws Error if browser is not launched\n\n * @returns {puppeteer.Browser} Puppeteer browser instance\n */\n getBrowser(): puppeteer.Browser {\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n return this.browser;\n }\n\n /**\n * Sets up listeners for browser page events\n * Tracks page creation and updates active page reference\n * @protected\n */\n protected async setupPageListener() {\n if (!this.browser) return;\n\n this.browser.on('targetcreated', async (target) => {\n const page = await target.page();\n if (page) {\n this.logger.info('New page created:', await page.url());\n this.activePage = page;\n\n page.once('close', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n\n page.once('error', () => {\n if (this.activePage === page) {\n this.activePage = null;\n }\n });\n }\n });\n }\n\n /**\n * Launches the browser with specified options\n * @abstract\n * @param {LaunchOptions} [options] - Browser launch configuration options\n * @returns {Promise<void>} Promise that resolves when browser is launched\n */\n abstract launch(options?: LaunchOptions): Promise<void>;\n\n /**\n * Closes the browser instance and cleans up resources\n * @returns {Promise<void>} Promise that resolves when browser is closed\n * @throws {Error} If browser fails to close properly\n */\n async close(): Promise<void> {\n this.logger.info('Closing browser');\n try {\n await this.browser?.close();\n this.browser = null;\n this.logger.success('Browser closed successfully');\n } catch (error) {\n this.logger.error('Failed to close browser:', error);\n throw error;\n }\n }\n\n /**\n * Creates a new page, navigates to the specified URL, executes a function in the page context, and returns the result\n * This method is inspired and modified from https://github.com/egoist/local-web-search/blob/04608ed09aa103e2fff6402c72ca12edfb692d19/src/browser.ts#L74\n * @template T - Type of parameters passed to the page function\n * @template R - Return type of the page function\n * @param {EvaluateOnNewPageOptions<T, R>} options - Configuration options for the page evaluation\n * @returns {Promise<R | null>} Promise resolving to the result of the page function or null\n * @throws {Error} If page creation or evaluation fails\n */\n async evaluateOnNewPage<T extends any[], R>(\n options: EvaluateOnNewPageOptions<T, R>,\n ): Promise<R | null> {\n const {\n url,\n pageFunction,\n pageFunctionParams,\n beforePageLoad,\n afterPageLoad,\n beforeSendResult,\n waitForOptions,\n } = options;\n const page = await this.browser!.newPage();\n try {\n await beforePageLoad?.(page);\n await page.goto(url, {\n waitUntil: 'networkidle2',\n ...waitForOptions,\n });\n await afterPageLoad?.(page);\n const _window = await page.evaluateHandle(() => window);\n const result = await page.evaluate(\n pageFunction,\n _window,\n ...pageFunctionParams,\n );\n await beforeSendResult?.(page, result);\n await _window.dispose();\n await page.close();\n return result;\n } catch (error) {\n await page.close();\n throw error;\n }\n }\n\n /**\n * Creates a new browser page\n * @returns {Promise<Page>} Promise resolving to the newly created page\n * @throws {Error} If browser is not launched or page creation fails\n */\n async createPage(): Promise<Page> {\n if (!this.browser) {\n this.logger.error('No active browser');\n throw new Error('Browser not launched');\n }\n const page = await this.browser.newPage();\n return page;\n }\n\n /**\n * Gets the currently active page or finds an active page if none is currently tracked\n * If no active pages exist, creates a new page\n * @returns {Promise<Page>} Promise resolving to the active page\n * @throws {Error} If browser is not launched or no active page can be found/created\n */\n async getActivePage(): Promise<Page> {\n if (!this.browser) {\n throw new Error('Browser not launched');\n }\n\n // If activePage exists and is still available, return directly\n if (this.activePage) {\n try {\n // Verify that the page is still available\n await this.activePage.evaluate(() => document.readyState);\n return this.activePage;\n } catch (e) {\n this.logger.warn('Active page no longer available:', e);\n this.activePage = null;\n }\n }\n\n // Get all pages and find the last active page\n const pages = await this.browser.pages();\n\n if (pages.length === 0) {\n this.activePage = await this.createPage();\n return this.activePage;\n }\n\n // Find the last responding page\n for (let i = pages.length - 1; i >= 0; i--) {\n const page = pages[i];\n try {\n await page.evaluate(() => document.readyState);\n this.activePage = page;\n return page;\n } catch (e) {\n continue;\n }\n }\n\n throw new Error('No active page found');\n }\n}","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { LaunchOptions } from './types.js';\nimport { BrowserFinder } from './finder.js';\nimport { BaseBrowser } from './base.js';\n\n/**\n * LocalBrowser class for controlling locally installed browsers\n * Extends the BaseBrowser with functionality specific to managing local browser instances\n * @extends BaseBrowser\n */\nexport class LocalBrowser extends BaseBrowser {\n /**\n * Browser finder instance to detect and locate installed browsers\n * @private\n */\n private browserFinder = new BrowserFinder();\n\n /**\n * Launches a local browser instance with specified options\n * Automatically detects installed browsers if no executable path is provided\n * @param {LaunchOptions} options - Configuration options for launching the browser\n * @returns {Promise<void>} Promise that resolves when the browser is successfully launched\n * @throws {Error} If the browser cannot be launched\n */\n async launch(options: LaunchOptions = {}): Promise<void> {\n this.logger.info('Launching browser with options:', options);\n\n const executablePath =\n options?.executablePath || this.browserFinder.findBrowser().executable;\n\n this.logger.info('Using executable path:', executablePath);\n\n const viewportWidth = options?.defaultViewport?.width ?? 1280;\n const viewportHeight = options?.defaultViewport?.height ?? 800;\n\n const puppeteerLaunchOptions: puppeteer.LaunchOptions = {\n executablePath,\n headless: options?.headless ?? false,\n defaultViewport: {\n width: viewportWidth,\n height: viewportHeight,\n },\n args: [\n '--no-sandbox',\n '--mute-audio',\n '--disable-gpu',\n '--disable-http2',\n '--disable-blink-features=AutomationControlled',\n '--disable-infobars',\n '--disable-background-timer-throttling',\n '--disable-popup-blocking',\n '--disable-backgrounding-occluded-windows',\n '--disable-renderer-backgrounding',\n '--disable-window-activation',\n '--disable-focus-on-load',\n '--no-default-browser-check', // disable default browser check\n '--disable-web-security', // disable CORS\n '--disable-features=IsolateOrigins,site-per-process',\n '--disable-site-isolation-trials',\n `--window-size=${viewportWidth},${viewportHeight + 90}`,\n options?.proxy ? `--proxy-server=${options.proxy}` : '',\n options?.profilePath\n ? `--profile-directory=${options.profilePath}`\n : '',\n ].filter(Boolean),\n ignoreDefaultArgs: ['--enable-automation'],\n timeout: options.timeout ?? 0,\n downloadBehavior: {\n policy: 'deny',\n },\n };\n\n this.logger.info('Launch options:', puppeteerLaunchOptions);\n\n try {\n this.browser = await puppeteer.launch(puppeteerLaunchOptions);\n await this.setupPageListener();\n this.logger.success('Browser launched successfully');\n } catch (error) {\n this.logger.error('Failed to launch browser:', error);\n throw error;\n }\n }\n}","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport * as puppeteer from 'puppeteer-core';\nimport { BaseBrowser, BaseBrowserOptions } from './base.js';\nimport { LaunchOptions } from './types.js';\n\n/**\n * Configuration options for RemoteBrowser\n * @extends BaseBrowserOptions\n * @interface RemoteBrowserOptions\n * @property {string} [wsEndpoint] - WebSocket endpoint URL for direct connection\n * @property {string} [host] - Remote host address (default: 'localhost')\n * @property {number} [port] - Remote debugging port (default: 9222)\n */\nexport interface RemoteBrowserOptions extends BaseBrowserOptions {\n wsEndpoint?: string;\n host?: string;\n port?: number;\n}\n\n/**\n * RemoteBrowser class for connecting to remote browser instances\n *\n * Currently, this RemoteBrowser is not production ready,\n * mainly because it still relies on `puppeteer-core`,\n * which can only run on Node.js.\n *\n * At the same time, Chrome instances built with\n * `--remote-debugging-address` on Linux have security risks\n *\n * @see https://issues.chromium.org/issues/41487252\n * @see https://issues.chromium.org/issues/40261787\n * @see https://github.com/pyppeteer/pyppeteer/pull/379\n * @see https://stackoverflow.com/questions/72760355/chrome-remote-debugging-not-working-computer-to-computer\n *\n * @extends BaseBrowser\n */\nexport class RemoteBrowser extends BaseBrowser {\n /**\n * Creates a new RemoteBrowser instance\n * @param {RemoteBrowserOptions} [options] - Configuration options for remote browser connection\n */\n constructor(private options?: RemoteBrowserOptions) {\n super(options);\n }\n\n /**\n * Connects to a remote browser instance using WebSocket\n * If no WebSocket endpoint is provided, attempts to discover it using the DevTools Protocol\n * @param {LaunchOptions} [options] - Launch configuration options\n * @returns {Promise<void>} Promise that resolves when connected to the remote browser\n * @throws {Error} If connection to the remote browser fails\n */\n async launch(options?: LaunchOptions): Promise<void> {\n this.logger.info('Browser Launch options:', options);\n\n let browserWSEndpoint = this.options?.wsEndpoint;\n\n if (!browserWSEndpoint) {\n const host = this.options?.host || 'localhost';\n const port = this.options?.port || 9222;\n const response = await fetch(`http://${host}:${port}/json/version`);\n const { webSocketDebuggerUrl } = await response.json();\n browserWSEndpoint = webSocketDebuggerUrl;\n }\n\n this.logger.info('Using WebSocket endpoint:', browserWSEndpoint);\n\n const puppeteerConnectOptions: puppeteer.ConnectOptions = {\n browserWSEndpoint,\n defaultViewport: options?.defaultViewport ?? { width: 1280, height: 800 },\n };\n\n try {\n this.browser = await puppeteer.connect(puppeteerConnectOptions);\n await this.setupPageListener();\n this.logger.success('Connected to remote browser successfully');\n } catch (error) {\n this.logger.error('Failed to connect to remote browser:', error);\n throw error;\n }\n }\n}","/**\n * PLEASE DO NOT MODIFY IT as it is generated by the build script\n *\n * Build: scripts/build-readability.ts\n * Source: https://github.com/mozilla/readability/blob/main/Readability.js\n */\n\n/**\n * Copyright (c) 2010 Arc90 Inc\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport const READABILITY_SCRIPT =\n 'function q(t,e){if(e&&e.documentElement)t=e,e=arguments[2];else if(!t||!t.documentElement)throw new Error(\"First argument to Readability constructor should be a document object.\");if(e=e||{},this._doc=t,this._docJSDOMParser=this._doc.firstChild.__JSDOMParser__,this._articleTitle=null,this._articleByline=null,this._articleDir=null,this._articleSiteName=null,this._attempts=[],this._debug=!!e.debug,this._maxElemsToParse=e.maxElemsToParse||this.DEFAULT_MAX_ELEMS_TO_PARSE,this._nbTopCandidates=e.nbTopCandidates||this.DEFAULT_N_TOP_CANDIDATES,this._charThreshold=e.charThreshold||this.DEFAULT_CHAR_THRESHOLD,this._classesToPreserve=this.CLASSES_TO_PRESERVE.concat(e.classesToPreserve||[]),this._keepClasses=!!e.keepClasses,this._serializer=e.serializer||function(i){return i.innerHTML},this._disableJSONLD=!!e.disableJSONLD,this._allowedVideoRegex=e.allowedVideoRegex||this.REGEXPS.videos,this._flags=this.FLAG_STRIP_UNLIKELYS|this.FLAG_WEIGHT_CLASSES|this.FLAG_CLEAN_CONDITIONALLY,this._debug){let i=function(r){if(r.nodeType==r.TEXT_NODE)return`${r.nodeName} (\"${r.textContent}\")`;let l=Array.from(r.attributes||[],function(a){return`${a.name}=\"${a.value}\"`}).join(\" \");return`<${r.localName} ${l}>`};this.log=function(){if(typeof console!=\"undefined\"){let l=Array.from(arguments,a=>a&&a.nodeType==this.ELEMENT_NODE?i(a):a);l.unshift(\"Reader: (Readability)\"),console.log.apply(console,l)}else if(typeof dump!=\"undefined\"){var r=Array.prototype.map.call(arguments,function(l){return l&&l.nodeName?i(l):l}).join(\" \");dump(\"Reader: (Readability) \"+r+`\\n`)}}}else this.log=function(){}}q.prototype={FLAG_STRIP_UNLIKELYS:1,FLAG_WEIGHT_CLASSES:2,FLAG_CLEAN_CONDITIONALLY:4,ELEMENT_NODE:1,TEXT_NODE:3,DEFAULT_MAX_ELEMS_TO_PARSE:0,DEFAULT_N_TOP_CANDIDATES:5,DEFAULT_TAGS_TO_SCORE:\"section,h2,h3,h4,h5,h6,p,td,pre\".toUpperCase().split(\",\"),DEFAULT_CHAR_THRESHOLD:500,REGEXPS:{unlikelyCandidates:/-ad-|ai2html|banner|breadcrumbs|combx|comment|community|cover-wrap|disqus|extra|footer|gdpr|header|legends|menu|related|remark|replies|rss|shoutbox|sidebar|skyscraper|social|sponsor|supplemental|ad-break|agegate|pagination|pager|popup|yom-remote/i,okMaybeItsACandidate:/and|article|body|column|content|main|shadow/i,positive:/article|body|content|entry|hentry|h-entry|main|page|pagination|post|text|blog|story/i,negative:/-ad-|hidden|^hid$| hid$| hid |^hid |banner|combx|comment|com-|contact|foot|footer|footnote|gdpr|masthead|media|meta|outbrain|promo|related|scroll|share|shoutbox|sidebar|skyscraper|sponsor|shopping|tags|tool|widget/i,extraneous:/print|archive|comment|discuss|e[\\\\-]?mail|share|reply|all|login|sign|single|utility/i,byline:/byline|author|dateline|writtenby|p-author/i,replaceFonts:/<(\\\\/?)font[^>]*>/gi,normalize:/\\\\s{2,}/g,videos:/\\\\/\\\\/(www\\\\.)?((dailymotion|youtube|youtube-nocookie|player\\\\.vimeo|v\\\\.qq)\\\\.com|(archive|upload\\\\.wikimedia)\\\\.org|player\\\\.twitch\\\\.tv)/i,shareElements:/(\\\\b|_)(share|sharedaddy)(\\\\b|_)/i,nextLink:/(next|weiter|continue|>([^\\\\|]|$)|»([^\\\\|]|$))/i,prevLink:/(prev|earl|old|new|<|«)/i,tokenize:/\\\\W+/g,whitespace:/^\\\\s*$/,hasContent:/\\\\S$/,hashUrl:/^#.+/,srcsetUrl:/(\\\\S+)(\\\\s+[\\\\d.]+[xw])?(\\\\s*(?:,|$))/g,b64DataUrl:/^data:\\\\s*([^\\\\s;,]+)\\\\s*;\\\\s*base64\\\\s*,/i,commas:/\\\\u002C|\\\\u060C|\\\\uFE50|\\\\uFE10|\\\\uFE11|\\\\u2E41|\\\\u2E34|\\\\u2E32|\\\\uFF0C/g,jsonLdArticleTypes:/^Article|AdvertiserContentArticle|NewsArticle|AnalysisNewsArticle|AskPublicNewsArticle|BackgroundNewsArticle|OpinionNewsArticle|ReportageNewsArticle|ReviewNewsArticle|Report|SatiricalArticle|ScholarlyArticle|MedicalScholarlyArticle|SocialMediaPosting|BlogPosting|LiveBlogPosting|DiscussionForumPosting|TechArticle|APIReference$/},UNLIKELY_ROLES:[\"menu\",\"menubar\",\"complementary\",\"navigation\",\"alert\",\"alertdialog\",\"dialog\"],DIV_TO_P_ELEMS:new Set([\"BLOCKQUOTE\",\"DL\",\"DIV\",\"IMG\",\"OL\",\"P\",\"PRE\",\"TABLE\",\"UL\"]),ALTER_TO_DIV_EXCEPTIONS:[\"DIV\",\"ARTICLE\",\"SECTION\",\"P\"],PRESENTATIONAL_ATTRIBUTES:[\"align\",\"background\",\"bgcolor\",\"border\",\"cellpadding\",\"cellspacing\",\"frame\",\"hspace\",\"rules\",\"style\",\"valign\",\"vspace\"],DEPRECATED_SIZE_ATTRIBUTE_ELEMS:[\"TABLE\",\"TH\",\"TD\",\"HR\",\"PRE\"],PHRASING_ELEMS:[\"ABBR\",\"AUDIO\",\"B\",\"BDO\",\"BR\",\"BUTTON\",\"CITE\",\"CODE\",\"DATA\",\"DATALIST\",\"DFN\",\"EM\",\"EMBED\",\"I\",\"IMG\",\"INPUT\",\"KBD\",\"LABEL\",\"MARK\",\"MATH\",\"METER\",\"NOSCRIPT\",\"OBJECT\",\"OUTPUT\",\"PROGRESS\",\"Q\",\"RUBY\",\"SAMP\",\"SCRIPT\",\"SELECT\",\"SMALL\",\"SPAN\",\"STRONG\",\"SUB\",\"SUP\",\"TEXTAREA\",\"TIME\",\"VAR\",\"WBR\"],CLASSES_TO_PRESERVE:[\"page\"],HTML_ESCAPE_MAP:{lt:\"<\",gt:\">\",amp:\"&\",quot:\\'\"\\',apos:\"\\'\"},_postProcessContent:function(t){this._fixRelativeUris(t),this._simplifyNestedElements(t),this._keepClasses||this._cleanClasses(t)},_removeNodes:function(t,e){if(this._docJSDOMParser&&t._isLiveNodeList)throw new Error(\"Do not pass live node lists to _removeNodes\");for(var i=t.length-1;i>=0;i--){var r=t[i],l=r.parentNode;l&&(!e||e.call(this,r,i,t))&&l.removeChild(r)}},_replaceNodeTags:function(t,e){if(this._docJSDOMParser&&t._isLiveNodeList)throw new Error(\"Do not pass live node lists to _replaceNodeTags\");for(let i of t)this._setNodeTag(i,e)},_forEachNode:function(t,e){Array.prototype.forEach.call(t,e,this)},_findNode:function(t,e){return Array.prototype.find.call(t,e,this)},_someNode:function(t,e){return Array.prototype.some.call(t,e,this)},_everyNode:function(t,e){return Array.prototype.every.call(t,e,this)},_concatNodeLists:function(){var t=Array.prototype.slice,e=t.call(arguments),i=e.map(function(r){return t.call(r)});return Array.prototype.concat.apply([],i)},_getAllNodesWithTag:function(t,e){return t.querySelectorAll?t.querySelectorAll(e.join(\",\")):[].concat.apply([],e.map(function(i){var r=t.getElementsByTagName(i);return Array.isArray(r)?r:Array.from(r)}))},_cleanClasses:function(t){var e=this._classesToPreserve,i=(t.getAttribute(\"class\")||\"\").split(/\\\\s+/).filter(function(r){return e.indexOf(r)!=-1}).join(\" \");for(i?t.setAttribute(\"class\",i):t.removeAttribute(\"class\"),t=t.firstElementChild;t;t=t.nextElementSibling)this._cleanClasses(t)},_fixRelativeUris:function(t){var e=this._doc.baseURI,i=this._doc.documentURI;function r(s){if(e==i&&s.charAt(0)==\"#\")return s;try{return new URL(s,e).href}catch(h){}return s}var l=this._getAllNodesWithTag(t,[\"a\"]);this._forEachNode(l,function(s){var h=s.getAttribute(\"href\");if(h)if(h.indexOf(\"javascript:\")===0)if(s.childNodes.length===1&&s.childNodes[0].nodeType===this.TEXT_NODE){var c=this._doc.createTextNode(s.textContent);s.parentNode.replaceChild(c,s)}else{for(var n=this._doc.createElement(\"span\");s.firstChild;)n.appendChild(s.firstChild);s.parentNode.replaceChild(n,s)}else s.setAttribute(\"href\",r(h))});var a=this._getAllNodesWithTag(t,[\"img\",\"picture\",\"figure\",\"video\",\"audio\",\"source\"]);this._forEachNode(a,function(s){var h=s.getAttribute(\"src\"),c=s.getAttribute(\"poster\"),n=s.getAttribute(\"srcset\");if(h&&s.setAttribute(\"src\",r(h)),c&&s.setAttribute(\"poster\",r(c)),n){var u=n.replace(this.REGEXPS.srcsetUrl,function(m,b,N,v){return r(b)+(N||\"\")+v});s.setAttribute(\"srcset\",u)}})},_simplifyNestedElements:function(t){for(var e=t;e;){if(e.parentNode&&[\"DIV\",\"SECTION\"].includes(e.tagName)&&!(e.id&&e.id.startsWith(\"readability\"))){if(this._isElementWithoutContent(e)){e=this._removeAndGetNext(e);continue}else if(this._hasSingleTagInsideElement(e,\"DIV\")||this._hasSingleTagInsideElement(e,\"SECTION\")){for(var i=e.children[0],r=0;r<e.attributes.length;r++)i.setAttribute(e.attributes[r].name,e.attributes[r].value);e.parentNode.replaceChild(i,e),e=i;continue}}e=this._getNextNode(e)}},_getArticleTitle:function(){var t=this._doc,e=\"\",i=\"\";try{e=i=t.title.trim(),typeof e!=\"string\"&&(e=i=this._getInnerText(t.getElementsByTagName(\"title\")[0]))}catch(u){}var r=!1;function l(u){return u.split(/\\\\s+/).length}if(/ [\\\\|\\\\-\\\\\\\\\\\\/>»] /.test(e))r=/ [\\\\\\\\\\\\/>»] /.test(e),e=i.replace(/(.*)[\\\\|\\\\-\\\\\\\\\\\\/>»] .*/gi,\"$1\"),l(e)<3&&(e=i.replace(/[^\\\\|\\\\-\\\\\\\\\\\\/>»]*[\\\\|\\\\-\\\\\\\\\\\\/>»](.*)/gi,\"$1\"));else if(e.indexOf(\": \")!==-1){var a=this._concatNodeLists(t.getElementsByTagName(\"h1\"),t.getElementsByTagName(\"h2\")),s=e.trim(),h=this._someNode(a,function(u){return u.textContent.trim()===s});h||(e=i.substring(i.lastIndexOf(\":\")+1),l(e)<3?e=i.substring(i.indexOf(\":\")+1):l(i.substr(0,i.indexOf(\":\")))>5&&(e=i))}else if(e.length>150||e.length<15){var c=t.getElementsByTagName(\"h1\");c.length===1&&(e=this._getInnerText(c[0]))}e=e.trim().replace(this.REGEXPS.normalize,\" \");var n=l(e);return n<=4&&(!r||n!=l(i.replace(/[\\\\|\\\\-\\\\\\\\\\\\/>»]+/g,\"\"))-1)&&(e=i),e},_prepDocument:function(){var t=this._doc;this._removeNodes(this._getAllNodesWithTag(t,[\"style\"])),t.body&&this._replaceBrs(t.body),this._replaceNodeTags(this._getAllNodesWithTag(t,[\"font\"]),\"SPAN\")},_nextNode:function(t){for(var e=t;e&&e.nodeType!=this.ELEMENT_NODE&&this.REGEXPS.whitespace.test(e.textContent);)e=e.nextSibling;return e},_replaceBrs:function(t){this._forEachNode(this._getAllNodesWithTag(t,[\"br\"]),function(e){for(var i=e.nextSibling,r=!1;(i=this._nextNode(i))&&i.tagName==\"BR\";){r=!0;var l=i.nextSibling;i.parentNode.removeChild(i),i=l}if(r){var a=this._doc.createElement(\"p\");for(e.parentNode.replaceChild(a,e),i=a.nextSibling;i;){if(i.tagName==\"BR\"){var s=this._nextNode(i.nextSibling);if(s&&s.tagName==\"BR\")break}if(!this._isPhrasingContent(i))break;var h=i.nextSibling;a.appendChild(i),i=h}for(;a.lastChild&&this._isWhitespace(a.lastChild);)a.removeChild(a.lastChild);a.parentNode.tagName===\"P\"&&this._setNodeTag(a.parentNode,\"DIV\")}})},_setNodeTag:function(t,e){if(this.log(\"_setNodeTag\",t,e),this._docJSDOMParser)return t.localName=e.toLowerCase(),t.tagName=e.toUpperCase(),t;for(var i=t.ownerDocument.createElement(e);t.firstChild;)i.appendChild(t.firstChild);t.parentNode.replaceChild(i,t),t.readability&&(i.readability=t.readability);for(var r=0;r<t.attributes.length;r++)try{i.setAttribute(t.attributes[r].name,t.attributes[r].value)}catch(l){}return i},_prepArticle:function(t){this._cleanStyles(t),this._markDataTables(t),this._fixLazyImages(t),this._cleanConditionally(t,\"form\"),this._cleanConditionally(t,\"fieldset\"),this._clean(t,\"object\"),this._clean(t,\"embed\"),this._clean(t,\"footer\"),this._clean(t,\"link\"),this._clean(t,\"aside\");var e=this.DEFAULT_CHAR_THRESHOLD;this._forEachNode(t.children,function(i){this._cleanMatchedNodes(i,function(r,l){return this.REGEXPS.shareElements.test(l)&&r.textContent.length<e})}),this._clean(t,\"iframe\"),this._clean(t,\"input\"),this._clean(t,\"textarea\"),this._clean(t,\"select\"),this._clean(t,\"button\"),this._cleanHeaders(t),this._cleanConditionally(t,\"table\"),this._cleanConditionally(t,\"ul\"),this._cleanConditionally(t,\"div\"),this._replaceNodeTags(this._getAllNodesWithTag(t,[\"h1\"]),\"h2\"),this._removeNodes(this._getAllNodesWithTag(t,[\"p\"]),function(i){var r=i.getElementsByTagName(\"img\").length,l=i.getElementsByTagName(\"embed\").length,a=i.getElementsByTagName(\"object\").length,s=i.getElementsByTagName(\"iframe\").length,h=r+l+a+s;return h===0&&!this._getInnerText(i,!1)}),this._forEachNode(this._getAllNodesWithTag(t,[\"br\"]),function(i){var r=this._nextNode(i.nextSibling);r&&r.tagName==\"P\"&&i.parentNode.removeChild(i)}),this._forEachNode(this._getAllNodesWithTag(t,[\"table\"]),function(i){var r=this._hasSingleTagInsideElement(i,\"TBODY\")?i.firstElementChild:i;if(this._hasSingleTagInsideElement(r,\"TR\")){var l=r.firstElementChild;if(this._hasSingleTagInsideElement(l,\"TD\")){var a=l.firstElementChild;a=this._setNodeTag(a,this._everyNode(a.childNodes,this._isPhrasingContent)?\"P\":\"DIV\"),i.parentNode.replaceChild(a,i)}}})},_initializeNode:function(t){switch(t.readability={contentScore:0},t.tagName){case\"DIV\":t.readability.contentScore+=5;break;case\"PRE\":case\"TD\":case\"BLOCKQUOTE\":t.readability.contentScore+=3;break;case\"ADDRESS\":case\"OL\":case\"UL\":case\"DL\":case\"DD\":case\"DT\":case\"LI\":case\"FORM\":t.readability.contentScore-=3;break;case\"H1\":case\"H2\":case\"H3\":case\"H4\":case\"H5\":case\"H6\":case\"TH\":t.readability.contentScore-=5;break}t.readability.contentScore+=this._getClassWeight(t)},_removeAndGetNext:function(t){var e=this._getNextNode(t,!0);return t.parentNode.removeChild(t),e},_getNextNode:function(t,e){if(!e&&t.firstElementChild)return t.firstElementChild;if(t.nextElementSibling)return t.nextElementSibling;do t=t.parentNode;while(t&&!t.nextElementSibling);return t&&t.nextElementSibling},_textSimilarity:function(t,e){var i=t.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean),r=e.toLowerCase().split(this.REGEXPS.tokenize).filter(Boolean);if(!i.length||!r.length)return 0;var l=r.filter(s=>!i.includes(s)),a=l.join(\" \").length/r.join(\" \").length;return 1-a},_checkByline:function(t,e){if(this._articleByline)return!1;if(t.getAttribute!==void 0)var i=t.getAttribute(\"rel\"),r=t.getAttribute(\"itemprop\");return(i===\"author\"||r&&r.indexOf(\"author\")!==-1||this.REGEXPS.byline.test(e))&&this._isValidByline(t.textContent)?(this._articleByline=t.textContent.trim(),!0):!1},_getNodeAncestors:function(t,e){e=e||0;for(var i=0,r=[];t.parentNode&&(r.push(t.parentNode),!(e&&++i===e));)t=t.parentNode;return r},_grabArticle:function(t){this.log(\"**** grabArticle ****\");var e=this._doc,i=t!==null;if(t=t||this._doc.body,!t)return this.log(\"No body found in document. Abort.\"),null;for(var r=t.innerHTML;;){this.log(\"Starting grabArticle loop\");var l=this._flagIsActive(this.FLAG_STRIP_UNLIKELYS),a=[],s=this._doc.documentElement;let J=!0;for(;s;){s.tagName===\"HTML\"&&(this._articleLang=s.getAttribute(\"lang\"));var h=s.className+\" \"+s.id;if(!this._isProbablyVisible(s)){this.log(\"Removing hidden node - \"+h),s=this._removeAndGetNext(s);continue}if(s.getAttribute(\"aria-modal\")==\"true\"&&s.getAttribute(\"role\")==\"dialog\"){s=this._removeAndGetNext(s);continue}if(this._checkByline(s,h)){s=this._removeAndGetNext(s);continue}if(J&&this._headerDuplicatesTitle(s)){this.log(\"Removing header: \",s.textContent.trim(),this._articleTitle.trim()),J=!1,s=this._removeAndGetNext(s);continue}if(l){if(this.REGEXPS.unlikelyCandidates.test(h)&&!this.REGEXPS.okMaybeItsACandidate.test(h)&&!this._hasAncestorTag(s,\"table\")&&!this._hasAncestorTag(s,\"code\")&&s.tagName!==\"BODY\"&&s.tagName!==\"A\"){this.log(\"Removing unlikely candidate - \"+h),s=this._removeAndGetNext(s);continue}if(this.UNLIKELY_ROLES.includes(s.getAttribute(\"role\"))){this.log(\"Removing content with role \"+s.getAttribute(\"role\")+\" - \"+h),s=this._removeAndGetNext(s);continue}}if((s.tagName===\"DIV\"||s.tagName===\"SECTION\"||s.tagName===\"HEADER\"||s.tagName===\"H1\"||s.tagName===\"H2\"||s.tagName===\"H3\"||s.tagName===\"H4\"||s.tagName===\"H5\"||s.tagName===\"H6\")&&this._isElementWithoutContent(s)){s=this._removeAndGetNext(s);continue}if(this.DEFAULT_TAGS_TO_SCORE.indexOf(s.tagName)!==-1&&a.push(s),s.tagName===\"DIV\"){for(var c=null,n=s.firstChild;n;){var u=n.nextSibling;if(this._isPhrasingContent(n))c!==null?c.appendChild(n):this._isWhitespace(n)||(c=e.createElement(\"p\"),s.replaceChild(c,n),c.appendChild(n));else if(c!==null){for(;c.lastChild&&this._isWhitespace(c.lastChild);)c.removeChild(c.lastChild);c=null}n=u}if(this._hasSingleTagInsideElement(s,\"P\")&&this._getLinkDensity(s)<.25){var m=s.children[0];s.parentNode.replaceChild(m,s),s=m,a.push(s)}else this._hasChildBlockElement(s)||(s=this._setNodeTag(s,\"P\"),a.push(s))}s=this._getNextNode(s)}var b=[];this._forEachNode(a,function(A){if(!(!A.parentNode||typeof A.parentNode.tagName==\"undefined\")){var T=this._getInnerText(A);if(!(T.length<25)){var K=this._getNodeAncestors(A,5);if(K.length!==0){var C=0;C+=1,C+=T.split(this.REGEXPS.commas).length,C+=Math.min(Math.floor(T.length/100),3),this._forEachNode(K,function(S,F){if(!(!S.tagName||!S.parentNode||typeof S.parentNode.tagName==\"undefined\")){if(typeof S.readability==\"undefined\"&&(this._initializeNode(S),b.push(S)),F===0)var X=1;else F===1?X=2:X=F*3;S.readability.contentScore+=C/X}})}}}});for(var N=[],v=0,y=b.length;v<y;v+=1){var E=b[v],d=E.readability.contentScore*(1-this._getLinkDensity(E));E.readability.contentScore=d,this.log(\"Candidate:\",E,\"with score \"+d);for(var p=0;p<this._nbTopCandidates;p++){var x=N[p];if(!x||d>x.readability.contentScore){N.splice(p,0,E),N.length>this._nbTopCandidates&&N.pop();break}}}var o=N[0]||null,L=!1,g;if(o===null||o.tagName===\"BODY\"){for(o=e.createElement(\"DIV\"),L=!0;t.firstChild;)this.log(\"Moving child out:\",t.firstChild),o.appendChild(t.firstChild);t.appendChild(o),this._initializeNode(o)}else if(o){for(var I=[],P=1;P<N.length;P++)N[P].readability.contentScore/o.readability.contentScore>=.75&&I.push(this._getNodeAncestors(N[P]));var O=3;if(I.length>=O)for(g=o.parentNode;g.tagName!==\"BODY\";){for(var G=0,H=0;H<I.length&&G<O;H++)G+=Number(I[H].includes(g));if(G>=O){o=g;break}g=g.parentNode}o.readability||this._initializeNode(o),g=o.parentNode;for(var M=o.readability.contentScore,Q=M/3;g.tagName!==\"BODY\";){if(!g.readability){g=g.parentNode;continue}var V=g.readability.contentScore;if(V<Q)break;if(V>M){o=g;break}M=g.readability.contentScore,g=g.parentNode}for(g=o.parentNode;g.tagName!=\"BODY\"&&g.children.length==1;)o=g,g=o.parentNode;o.readability||this._initializeNode(o)}var _=e.createElement(\"DIV\");i&&(_.id=\"readability-content\");var Z=Math.max(10,o.readability.contentScore*.2);g=o.parentNode;for(var U=g.children,w=0,j=U.length;w<j;w++){var f=U[w],R=!1;if(this.log(\"Looking at sibling node:\",f,f.readability?\"with score \"+f.readability.contentScore:\"\"),this.log(\"Sibling has score\",f.readability?f.readability.contentScore:\"Unknown\"),f===o)R=!0;else{var $=0;if(f.className===o.className&&o.className!==\"\"&&($+=o.readability.contentScore*.2),f.readability&&f.readability.contentScore+$>=Z)R=!0;else if(f.nodeName===\"P\"){var Y=this._getLinkDensity(f),z=this._getInnerText(f),k=z.length;(k>80&&Y<.25||k<80&&k>0&&Y===0&&z.search(/\\\\.( |$)/)!==-1)&&(R=!0)}}R&&(this.log(\"Appending node:\",f),this.ALTER_TO_DIV_EXCEPTIONS.indexOf(f.nodeName)===-1&&(this.log(\"Altering sibling:\",f,\"to div.\"),f=this._setNodeTag(f,\"DIV\")),_.appendChild(f),U=g.children,w-=1,j-=1)}if(this._debug&&this.log(\"Article content pre-prep: \"+_.innerHTML),this._prepArticle(_),this._debug&&this.log(\"Article content post-prep: \"+_.innerHTML),L)o.id=\"readability-page-1\",o.className=\"page\";else{var B=e.createElement(\"DIV\");for(B.id=\"readability-page-1\",B.className=\"page\";_.firstChild;)B.appendChild(_.firstChild);_.appendChild(B)}this._debug&&this.log(\"Article content after paging: \"+_.innerHTML);var W=!0,D=this._getInnerText(_,!0).length;if(D<this._charThreshold)if(W=!1,t.innerHTML=r,this._flagIsActive(this.FLAG_STRIP_UNLIKELYS))this._removeFlag(this.FLAG_STRIP_UNLIKELYS),this._attempts.push({articleContent:_,textLength:D});else if(this._flagIsActive(this.FLAG_WEIGHT_CLASSES))this._removeFlag(this.FLAG_WEIGHT_CLASSES),this._attempts.push({articleContent:_,textLength:D});else if(this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY))this._removeFlag(this.FLAG_CLEAN_CONDITIONALLY),this._attempts.push({articleContent:_,textLength:D});else{if(this._attempts.push({articleContent:_,textLength:D}),this._attempts.sort(function(A,T){return T.textLength-A.textLength}),!this._attempts[0].textLength)return null;_=this._attempts[0].articleContent,W=!0}if(W){var tt=[g,o].concat(this._getNodeAncestors(g));return this._someNode(tt,function(A){if(!A.tagName)return!1;var T=A.getAttribute(\"dir\");return T?(this._articleDir=T,!0):!1}),_}}},_isValidByline:function(t){return typeof t==\"string\"||t instanceof String?(t=t.trim(),t.length>0&&t.length<100):!1},_unescapeHtmlEntities:function(t){if(!t)return t;var e=this.HTML_ESCAPE_MAP;return t.replace(/&(quot|amp|apos|lt|gt);/g,function(i,r){return e[r]}).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi,function(i,r,l){var a=parseInt(r||l,r?16:10);return String.fromCharCode(a)})},_getJSONLD:function(t){var e=this._getAllNodesWithTag(t,[\"script\"]),i;return this._forEachNode(e,function(r){if(!i&&r.getAttribute(\"type\")===\"application/ld+json\")try{var l=r.textContent.replace(/^\\\\s*<!\\\\[CDATA\\\\[|\\\\]\\\\]>\\\\s*$/g,\"\"),a=JSON.parse(l);if(!a[\"@context\"]||!a[\"@context\"].match(/^https?\\\\:\\\\/\\\\/schema\\\\.org$/)||(!a[\"@type\"]&&Array.isArray(a[\"@graph\"])&&(a=a[\"@graph\"].find(function(n){return(n[\"@type\"]||\"\").match(this.REGEXPS.jsonLdArticleTypes)})),!a||!a[\"@type\"]||!a[\"@type\"].match(this.REGEXPS.jsonLdArticleTypes)))return;if(i={},typeof a.name==\"string\"&&typeof a.headline==\"string\"&&a.name!==a.headline){var s=this._getArticleTitle(),h=this._textSimilarity(a.name,s)>.75,c=this._textSimilarity(a.headline,s)>.75;c&&!h?i.title=a.headline:i.title=a.name}else typeof a.name==\"string\"?i.title=a.name.trim():typeof a.headline==\"string\"&&(i.title=a.headline.trim());a.author&&(typeof a.author.name==\"string\"?i.byline=a.author.name.trim():Array.isArray(a.author)&&a.author[0]&&typeof a.author[0].name==\"string\"&&(i.byline=a.author.filter(function(n){return n&&typeof n.name==\"string\"}).map(function(n){return n.name.trim()}).join(\", \"))),typeof a.description==\"string\"&&(i.excerpt=a.description.trim()),a.publisher&&typeof a.publisher.name==\"string\"&&(i.siteName=a.publisher.name.trim()),typeof a.datePublished==\"string\"&&(i.datePublished=a.datePublished.trim());return}catch(n){this.log(n.message)}}),i||{}},_getArticleMetadata:function(t){var e={},i={},r=this._doc.getElementsByTagName(\"meta\"),l=/\\\\s*(article|dc|dcterm|og|twitter)\\\\s*:\\\\s*(author|creator|description|published_time|title|site_name)\\\\s*/gi,a=/^\\\\s*(?:(dc|dcterm|og|twitter|weibo:(article|webpage))\\\\s*[\\\\.:]\\\\s*)?(author|creator|description|title|site_name)\\\\s*$/i;return this._forEachNode(r,function(s){var h=s.getAttribute(\"name\"),c=s.getAttribute(\"property\"),n=s.getAttribute(\"content\");if(n){var u=null,m=null;c&&(u=c.match(l),u&&(m=u[0].toLowerCase().replace(/\\\\s/g,\"\"),i[m]=n.trim())),!u&&h&&a.test(h)&&(m=h,n&&(m=m.toLowerCase().replace(/\\\\s/g,\"\").replace(/\\\\./g,\":\"),i[m]=n.trim()))}}),e.title=t.title||i[\"dc:title\"]||i[\"dcterm:title\"]||i[\"og:title\"]||i[\"weibo:article:title\"]||i[\"weibo:webpage:title\"]||i.title||i[\"twitter:title\"],e.title||(e.title=this._getArticleTitle()),e.byline=t.byline||i[\"dc:creator\"]||i[\"dcterm:creator\"]||i.author,e.excerpt=t.excerpt||i[\"dc:description\"]||i[\"dcterm:description\"]||i[\"og:description\"]||i[\"weibo:article:description\"]||i[\"weibo:webpage:description\"]||i.description||i[\"twitter:description\"],e.siteName=t.siteName||i[\"og:site_name\"],e.publishedTime=t.datePublished||i[\"article:published_time\"]||null,e.title=this._unescapeHtmlEntities(e.title),e.byline=this._unescapeHtmlEntities(e.byline),e.excerpt=this._unescapeHtmlEntities(e.excerpt),e.siteName=this._unescapeHtmlEntities(e.siteName),e.publishedTime=this._unescapeHtmlEntities(e.publishedTime),e},_isSingleImage:function(t){return t.tagName===\"IMG\"?!0:t.children.length!==1||t.textContent.trim()!==\"\"?!1:this._isSingleImage(t.children[0])},_unwrapNoscriptImages:function(t){var e=Array.from(t.getElementsByTagName(\"img\"));this._forEachNode(e,function(r){for(var l=0;l<r.attributes.length;l++){var a=r.attributes[l];switch(a.name){case\"src\":case\"srcset\":case\"data-src\":case\"data-srcset\":return}if(/\\\\.(jpg|jpeg|png|webp)/i.test(a.value))return}r.parentNode.removeChild(r)});var i=Array.from(t.getElementsByTagName(\"noscript\"));this._forEachNode(i,function(r){var l=t.createElement(\"div\");if(l.innerHTML=r.innerHTML,!!this._isSingleImage(l)){var a=r.previousElementSibling;if(a&&this._isSingleImage(a)){var s=a;s.tagName!==\"IMG\"&&(s=a.getElementsByTagName(\"img\")[0]);for(var h=l.getElementsByTagName(\"img\")[0],c=0;c<s.attributes.length;c++){var n=s.attributes[c];if(n.value!==\"\"&&(n.name===\"src\"||n.name===\"srcset\"||/\\\\.(jpg|jpeg|png|webp)/i.test(n.value))){if(h.getAttribute(n.name)===n.value)continue;var u=n.name;h.hasAttribute(u)&&(u=\"data-old-\"+u),h.setAttribute(u,n.value)}}r.parentNode.replaceChild(l.firstElementChild,a)}}})},_removeScripts:function(t){this._removeNodes(this._getAllNodesWithTag(t,[\"script\",\"noscript\"]))},_hasSingleTagInsideElement:function(t,e){return t.children.length!=1||t.children[0].tagName!==e?!1:!this._someNode(t.childNodes,function(i){return i.nodeType===this.TEXT_NODE&&this.REGEXPS.hasContent.test(i.textContent)})},_isElementWithoutContent:function(t){return t.nodeType===this.ELEMENT_NODE&&t.textContent.trim().length==0&&(t.children.length==0||t.children.length==t.getElementsByTagName(\"br\").length+t.getElementsByTagName(\"hr\").length)},_hasChildBlockElement:function(t){return this._someNode(t.childNodes,function(e){return this.DIV_TO_P_ELEMS.has(e.tagName)||this._hasChildBlockElement(e)})},_isPhrasingContent:function(t){return t.nodeType===this.TEXT_NODE||this.PHRASING_ELEMS.indexOf(t.tagName)!==-1||(t.tagName===\"A\"||t.tagName===\"DEL\"||t.tagName===\"INS\")&&this._everyNode(t.childNodes,this._isPhrasingContent)},_isWhitespace:function(t){return t.nodeType===this.TEXT_NODE&&t.textContent.trim().length===0||t.nodeType===this.ELEMENT_NODE&&t.tagName===\"BR\"},_getInnerText:function(t,e){e=typeof e==\"undefined\"?!0:e;var i=t.textContent.trim();return e?i.replace(this.REGEXPS.normalize,\" \"):i},_getCharCount:function(t,e){return e=e||\",\",this._getInnerText(t).split(e).length-1},_cleanStyles:function(t){if(!(!t||t.tagName.toLowerCase()===\"svg\")){for(var e=0;e<this.PRESENTATIONAL_ATTRIBUTES.length;e++)t.removeAttribute(this.PRESENTATIONAL_ATTRIBUTES[e]);this.DEPRECATED_SIZE_ATTRIBUTE_ELEMS.indexOf(t.tagName)!==-1&&(t.removeAttribute(\"width\"),t.removeAttribute(\"height\"));for(var i=t.firstElementChild;i!==null;)this._cleanStyles(i),i=i.nextElementSibling}},_getLinkDensity:function(t){var e=this._getInnerText(t).length;if(e===0)return 0;var i=0;return this._forEachNode(t.getElementsByTagName(\"a\"),function(r){var l=r.getAttribute(\"href\"),a=l&&this.REGEXPS.hashUrl.test(l)?.3:1;i+=this._getInnerText(r).length*a}),i/e},_getClassWeight:function(t){if(!this._flagIsActive(this.FLAG_WEIGHT_CLASSES))return 0;var e=0;return typeof t.className==\"string\"&&t.className!==\"\"&&(this.REGEXPS.negative.test(t.className)&&(e-=25),this.REGEXPS.positive.test(t.className)&&(e+=25)),typeof t.id==\"string\"&&t.id!==\"\"&&(this.REGEXPS.negative.test(t.id)&&(e-=25),this.REGEXPS.positive.test(t.id)&&(e+=25)),e},_clean:function(t,e){var i=[\"object\",\"embed\",\"iframe\"].indexOf(e)!==-1;this._removeNodes(this._getAllNodesWithTag(t,[e]),function(r){if(i){for(var l=0;l<r.attributes.length;l++)if(this._allowedVideoRegex.test(r.attributes[l].value))return!1;if(r.tagName===\"object\"&&this._allowedVideoRegex.test(r.innerHTML))return!1}return!0})},_hasAncestorTag:function(t,e,i,r){i=i||3,e=e.toUpperCase();for(var l=0;t.parentNode;){if(i>0&&l>i)return!1;if(t.parentNode.tagName===e&&(!r||r(t.parentNode)))return!0;t=t.parentNode,l++}return!1},_getRowAndColumnCount:function(t){for(var e=0,i=0,r=t.getElementsByTagName(\"tr\"),l=0;l<r.length;l++){var a=r[l].getAttribute(\"rowspan\")||0;a&&(a=parseInt(a,10)),e+=a||1;for(var s=0,h=r[l].getElementsByTagName(\"td\"),c=0;c<h.length;c++){var n=h[c].getAttribute(\"colspan\")||0;n&&(n=parseInt(n,10)),s+=n||1}i=Math.max(i,s)}return{rows:e,columns:i}},_markDataTables:function(t){for(var e=t.getElementsByTagName(\"table\"),i=0;i<e.length;i++){var r=e[i],l=r.getAttribute(\"role\");if(l==\"presentation\"){r._readabilityDataTable=!1;continue}var a=r.getAttribute(\"datatable\");if(a==\"0\"){r._readabilityDataTable=!1;continue}var s=r.getAttribute(\"summary\");if(s){r._readabilityDataTable=!0;continue}var h=r.getElementsByTagName(\"caption\")[0];if(h&&h.childNodes.length>0){r._readabilityDataTable=!0;continue}var c=[\"col\",\"colgroup\",\"tfoot\",\"thead\",\"th\"],n=function(m){return!!r.getElementsByTagName(m)[0]};if(c.some(n)){this.log(\"Data table because found data-y descendant\"),r._readabilityDataTable=!0;continue}if(r.getElementsByTagName(\"table\")[0]){r._readabilityDataTable=!1;continue}var u=this._getRowAndColumnCount(r);if(u.rows>=10||u.columns>4){r._readabilityDataTable=!0;continue}r._readabilityDataTable=u.rows*u.columns>10}},_fixLazyImages:function(t){this._forEachNode(this._getAllNodesWithTag(t,[\"img\",\"picture\",\"figure\"]),function(e){if(e.src&&this.REGEXPS.b64DataUrl.test(e.src)){var i=this.REGEXPS.b64DataUrl.exec(e.src);if(i[1]===\"image/svg+xml\")return;for(var r=!1,l=0;l<e.attributes.length;l++){var a=e.attributes[l];if(a.name!==\"src\"&&/\\\\.(jpg|jpeg|png|webp)/i.test(a.value)){r=!0;break}}if(r){var s=e.src.search(/base64\\\\s*/i)+7,h=e.src.length-s;h<133&&e.removeAttribute(\"src\")}}if(!((e.src||e.srcset&&e.srcset!=\"null\")&&e.className.toLowerCase().indexOf(\"lazy\")===-1)){for(var c=0;c<e.attributes.length;c++)if(a=e.attributes[c],!(a.name===\"src\"||a.name===\"srcset\"||a.name===\"alt\")){var n=null;if(/\\\\.(jpg|jpeg|png|webp)\\\\s+\\\\d/.test(a.value)?n=\"srcset\":/^\\\\s*\\\\S+\\\\.(jpg|jpeg|png|webp)\\\\S*\\\\s*$/.test(a.value)&&(n=\"src\"),n){if(e.tagName===\"IMG\"||e.tagName===\"PICTURE\")e.setAttribute(n,a.value);else if(e.tagName===\"FIGURE\"&&!this._getAllNodesWithTag(e,[\"img\",\"picture\"]).length){var u=this._doc.createElement(\"img\");u.setAttribute(n,a.value),e.appendChild(u)}}}}})},_getTextDensity:function(t,e){var i=this._getInnerText(t,!0).length;if(i===0)return 0;var r=0,l=this._getAllNodesWithTag(t,e);return this._forEachNode(l,a=>r+=this._getInnerText(a,!0).length),r/i},_cleanConditionally:function(t,e){this._flagIsActive(this.FLAG_CLEAN_CONDITIONALLY)&&this._removeNodes(this._getAllNodesWithTag(t,[e]),function(i){var r=function(g){return g._readabilityDataTable},l=e===\"ul\"||e===\"ol\";if(!l){var a=0,s=this._getAllNodesWithTag(i,[\"ul\",\"ol\"]);this._forEachNode(s,g=>a+=this._getInnerText(g).length),l=a/this._getInnerText(i).length>.9}if(e===\"table\"&&r(i)||this._hasAncestorTag(i,\"table\",-1,r)||this._hasAncestorTag(i,\"code\"))return!1;var h=this._getClassWeight(i);this.log(\"Cleaning Conditionally\",i);var c=0;if(h+c<0)return!0;if(this._getCharCount(i,\",\")<10){for(var n=i.getElementsByTagName(\"p\").length,u=i.getElementsByTagName(\"img\").length,m=i.getElementsByTagName(\"li\").length-100,b=i.getElementsByTagName(\"input\").length,N=this._getTextDensity(i,[\"h1\",\"h2\",\"h3\",\"h4\",\"h5\",\"h6\"]),v=0,y=this._getAllNodesWithTag(i,[\"object\",\"embed\",\"iframe\"]),E=0;E<y.length;E++){for(var d=0;d<y[E].attributes.length;d++)if(this._allowedVideoRegex.test(y[E].attributes[d].value))return!1;if(y[E].tagName===\"object\"&&this._allowedVideoRegex.test(y[E].innerHTML))return!1;v++}var p=this._getLinkDensity(i),x=this._getInnerText(i).length,o=u>1&&n/u<.5&&!this._hasAncestorTag(i,\"figure\")||!l&&m>n||b>Math.floor(n/3)||!l&&N<.9&&x<25&&(u===0||u>2)&&!this._hasAncestorTag(i,\"figure\")||!l&&h<25&&p>.2||h>=25&&p>.5||v===1&&x<75||v>1;if(l&&o){for(var L=0;L<i.children.length;L++)if(i.children[L].children.length>1)return o;let g=i.getElementsByTagName(\"li\").length;if(u==g)return!1}return o}return!1})},_cleanMatchedNodes:function(t,e){for(var i=this._getNextNode(t,!0),r=this._getNextNode(t);r&&r!=i;)e.call(this,r,r.className+\" \"+r.id)?r=this._removeAndGetNext(r):r=this._getNextNode(r)},_cleanHeaders:function(t){let e=this._getAllNodesWithTag(t,[\"h1\",\"h2\"]);this._removeNodes(e,function(i){let r=this._getClassWeight(i)<0;return r&&this.log(\"Removing header with low class weight:\",i),r})},_headerDuplicatesTitle:function(t){if(t.tagName!=\"H1\"&&t.tagName!=\"H2\")return!1;var e=this._getInnerText(t,!1);return this.log(\"Evaluating similarity of header:\",e,this._articleTitle),this._textSimilarity(this._articleTitle,e)>.75},_flagIsActive:function(t){return(this._flags&t)>0},_removeFlag:function(t){this._flags=this._flags&~t},_isProbablyVisible:function(t){return(!t.style||t.style.display!=\"none\")&&(!t.style||t.style.visibility!=\"hidden\")&&!t.hasAttribute(\"hidden\")&&(!t.hasAttribute(\"aria-hidden\")||t.getAttribute(\"aria-hidden\")!=\"true\"||t.className&&t.className.indexOf&&t.className.indexOf(\"fallback-image\")!==-1)},parse:function(){if(this._maxElemsToParse>0){var t=this._doc.getElementsByTagName(\"*\").length;if(t>this._maxElemsToParse)throw new Error(\"Aborting parsing document; \"+t+\" elements found\")}this._unwrapNoscriptImages(this._doc);var e=this._disableJSONLD?{}:this._getJSONLD(this._doc);this._removeScripts(this._doc),this._prepDocument();var i=this._getArticleMetadata(e);this._articleTitle=i.title;var r=this._grabArticle();if(!r)return null;if(this.log(\"Grabbed: \"+r.innerHTML),this._postProcessContent(r),!i.excerpt){var l=r.getElementsByTagName(\"p\");l.length>0&&(i.excerpt=l[0].textContent.trim())}var a=r.textContent;return{title:this._articleTitle,byline:i.byline||this._articleByline,dir:this._articleDir,lang:this._articleLang,content:this._serializer(r),textContent:a,length:a.length,excerpt:i.excerpt,siteName:i.siteName||this._articleSiteName,publishedTime:i.publishedTime}}};typeof module==\"object\"&&(module.exports=q);\\n';","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { LocalBrowser, type BrowserInterface } from '../browser/index.js';\nimport { READABILITY_SCRIPT } from './readability.js';\nimport { Logger, defaultLogger } from '@agent-infra/logger';\nimport {\n extractPageInformation,\n toMarkdown,\n} from './utils.js';\nimport { PromiseQueue } from './queue.js';\nimport { shouldSkipDomain, interceptRequest } from './utils.js';\nimport { getSearchEngine } from './engines/index.js';\nimport type {\n SearchResult,\n BrowserSearchOptions,\n BrowserSearchConfig,\n LocalBrowserSearchEngine,\n} from './types.js';\n\n/**\n * Service class for performing web searches and content extraction\n */\nexport class BrowserSearch {\n private logger: Logger;\n private browser: BrowserInterface;\n private isBrowserOpen = false;\n private defaultEngine: LocalBrowserSearchEngine;\n\n constructor(private config: BrowserSearchConfig = {}) {\n this.logger = config?.logger ?? defaultLogger;\n this.browser = config.browser ?? new LocalBrowser({ logger: this.logger });\n this.defaultEngine = config.defaultEngine ?? 'bing';\n }\n\n /**\n * Search web and extract content from result pages\n */\n async perform(options: BrowserSearchOptions) {\n this.logger.info('Starting search with options:', options);\n\n const queries = Array.isArray(options.query)\n ? options.query\n : [options.query];\n const excludeDomains = options.excludeDomains || [];\n const count =\n options.count && Math.max(3, Math.floor(options.count / queries.length));\n const engine = options.engine || this.defaultEngine;\n\n try {\n if (!this.isBrowserOpen) {\n this.logger.info('Launching browser');\n await this.browser.launch(this.config.browserOptions);\n this.isBrowserOpen = true;\n } else {\n this.logger.info('Using existing browser instance');\n }\n\n const queue = new PromiseQueue(options.concurrency || 15);\n const visitedUrls = new Set<string>();\n const results = await Promise.all(\n queries.map((query) =>\n this.search(this.browser, {\n query,\n count,\n queue,\n visitedUrls,\n excludeDomains,\n truncate: options.truncate,\n needVisitedUrls: options.needVisitedUrls,\n engine,\n }),\n ),\n );\n\n this.logger.success('Search completed successfully');\n return results.flat();\n } catch (error) {\n this.logger.error('Search failed:', error);\n return [];\n } finally {\n if (!options.keepBrowserOpen && this.isBrowserOpen) {\n await this.closeBrowser();\n }\n }\n }\n\n /**\n * Explicitly close the browser instance\n */\n async closeBrowser(): Promise<void> {\n if (this.isBrowserOpen) {\n this.logger.info('Closing browser');\n await this.browser.close();\n this.isBrowserOpen = false;\n }\n }\n\n private async search(\n browser: BrowserInterface,\n options: {\n query: string;\n count?: number;\n needVisitedUrls?: boolean;\n excludeDomains: string[];\n queue: PromiseQueue;\n visitedUrls: Set<string>;\n truncate?: number;\n engine: LocalBrowserSearchEngine;\n },\n ) {\n const searchEngine = getSearchEngine(options.engine);\n const url = searchEngine.getSearchUrl(options.query, {\n count: options.count,\n excludeDomains: options.excludeDomains,\n });\n\n this.logger.info(`Searching with ${options.engine} engine: ${url}`);\n\n let links = await browser.evaluateOnNewPage({\n url,\n waitForOptions: {\n waitUntil: 'networkidle0',\n },\n pageFunction: searchEngine.extractSearchResults,\n pageFunctionParams: [],\n beforePageLoad: async (page) => {\n await interceptRequest(page);\n },\n afterPageLoad: async (page) => {\n // const content = await page.screenshot({\n // type: 'jpeg',\n // quality: 50,\n // encoding: 'base64',\n // });\n // this.logger.info('Page content:', content);\n if (searchEngine.waitForSearchResults)\n await searchEngine.waitForSearchResults(page, 10000);\n },\n });\n\n this.logger.info(`Fetched ${links?.length ?? 0} links`);\n\n // Filter links\n links =\n links?.filter((link) => {\n if (options.visitedUrls.has(link.url)) return false;\n options.visitedUrls.add(link.url);\n return !shouldSkipDomain(link.url);\n }) || [];\n\n if (!links.length) {\n this.logger.info('No valid links found');\n return [];\n }\n\n // Visit each link and extract content\n const results = await Promise.allSettled(\n options.needVisitedUrls\n ? links.map((item) =>\n options.queue.add(() => this.visitLink(this.browser, item)),\n )\n : links,\n );\n\n return results\n .map((result) => {\n if (result.status === 'rejected' || !result.value) return null;\n\n return {\n ...result.value,\n content: options.truncate\n ? result.value.content.slice(0, options.truncate)\n : result.value.content,\n };\n }).filter((v): v is SearchResult => v !== null);\n }\n\n private async visitLink(\n browser: BrowserInterface,\n item: SearchResult,\n ): Promise<SearchResult | undefined> {\n try {\n this.logger.info('Visiting link:', item.url);\n\n const result = await browser.evaluateOnNewPage({\n url: item.url,\n pageFunction: extractPageInformation,\n pageFunctionParams: [READABILITY_SCRIPT],\n beforePageLoad: async (page) => {\n await interceptRequest(page);\n },\n });\n\n if (result) {\n const content = toMarkdown(result.content);\n return { ...result, url: item.url, content, snippet: item.snippet };\n }\n } catch (e) {\n this.logger.error('Failed to visit link:', e);\n }\n }\n}\n\ndeclare global {\n interface Window {\n Readability: any;\n }\n}\n","/**\n * The following code is based on\n * https://github.com/bytedance/UI-TARS-desktop/tree/main/packages/agent-infra/search/browser-search\n * \n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport Turndown from 'turndown';\nimport { gfm } from 'turndown-plugin-gfm';\nimport { defaultLogger as logger } from '@agent-infra/logger';\nimport { Page } from '../browser/index.js';\nimport UserAgent from 'user-agents';\n\n/**\n * Safely parses a URL string into a URL object\n * @param url - The URL string to parse\n * @returns URL object or null if invalid\n */\nconst parseUrl = (url: string) => {\n try {\n return new URL(url);\n } catch {\n return null;\n }\n};\n\n/**\n * Determines if a domain should be skipped based on a blocklist\n * @param url - The URL to check\n * @returns True if the domain should be skipped, false otherwise\n */\nexport const shouldSkipDomain = (url: string) => {\n const parsed = parseUrl(url);\n if (!parsed) return true;\n\n const { hostname } = parsed;\n return [\n 'reddit.com',\n 'www.reddit.com',\n 'x.com',\n 'twitter.com',\n 'www.twitter.com',\n 'youtube.com',\n 'www.youtube.com',\n ].includes(hostname);\n};\n\n/**\n * Applies various stealth techniques to make the browser appear more like a regular user browser\n * @param page - Puppeteer page object\n */\nexport async function applyStealthScripts(page: Page) {\n const userAgent = new UserAgent({\n deviceCategory: 'desktop',\n }).toString();\n await page.setBypassCSP(true);\n await page.setUserAgent(userAgent);\n\n /**\n * https://intoli.com/blog/not-possible-to-block-chrome-headless/chrome-headless-test.html\n */\n await page.evaluate(() => {\n /**\n * Override the navigator.webdriver property\n * The webdriver read-only property of the navigator interface indicates whether the user agent is controlled by automation.\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Navigator/webdriver\n */\n Object.defineProperty(navigator, 'webdriver', {\n get: () => undefined,\n });\n\n // Mock languages and plugins to mimic a real browser\n Object.defineProperty(navigator, 'languages', {\n get: () => ['en-US', 'en'],\n });\n\n Object.defineProperty(navigator, 'plugins', {\n get: () => [{}, {}, {}, {}, {}],\n });\n\n // Redefine the headless property\n Object.defineProperty(navigator, 'headless', {\n get: () => false,\n });\n\n // Override the permissions API\n const originalQuery = window.navigator.permissions.query;\n window.navigator.permissions.query = (parameters) =>\n parameters.name === 'notifications'\n ? Promise.resolve({\n state: Notification.permission,\n } as PermissionStatus)\n : originalQuery(parameters);\n });\n}\n\n/**\n * Sets up request interception to block unnecessary resources and apply stealth techniques\n * @param page - Puppeteer page object\n */\nexport async function interceptRequest(page: Page) {\n await applyStealthScripts(page);\n await page.setRequestInterception(true);\n\n page.on('request', (request) => {\n const resourceType = request.resourceType();\n\n if (resourceType !== 'document') {\n return request.abort();\n }\n\n if (request.isNavigationRequest()) {\n return request.continue();\n }\n\n return request.abort();\n });\n}\n\n/**\n * Interface representing extracted page information\n */\ninterface PageInfo {\n /** Page title */\n title: string;\n /** Page content in HTML format */\n content: string;\n}\n\n/**\n * !NOTE: This function runs in the context of the browser page, not Node.js\n * \n * Extracts readable content from a web page using Readability\n * @param window Browser window object\n * @param readabilityScript Readability library script as string\n * @returns Extracted page information (title and content)\n */\nexport function extractPageInformation(\n window: Window,\n readabilityScript: string,\n): PageInfo {\n const Readability = new Function(\n 'module',\n `${readabilityScript}\\nreturn module.exports`,\n )({});\n\n const document = window.document;\n\n // Remove non-content elements to improve extraction quality\n document\n .querySelectorAll(\n 'script,noscript,style,link,svg,img,video,iframe,canvas,.reflist',\n )\n .forEach((el) => el.remove());\n\n // Parse the document using Readability\n const article = new Readability(document).parse();\n const content = article?.content || '';\n const title = document.title;\n\n return {\n content,\n title: article?.title || title,\n };\n}\n\nexport interface ToMarkdownOptions extends Turndown.Options {\n gfmExtension?: boolean;\n}\n\n/**\n * Convert HTML content to Markdown format\n * @param html HTML string\n * @param options Conversion options\n * @returns Markdown string\n */\nexport function toMarkdown(\n html: string,\n options: ToMarkdownOptions = {},\n): string {\n if (!html) return '';\n\n try {\n const {\n codeBlockStyle = 'fenced',\n headingStyle = 'atx',\n emDelimiter = '*',\n strongDelimiter = '**',\n gfmExtension = true,\n } = options;\n\n const turndown = new Turndown({\n codeBlockStyle,\n headingStyle,\n emDelimiter,\n strongDelimiter,\n });\n\n if (gfmExtension) {\n turndown.use(gfm);\n }\n\n return turndown.turndown(html);\n } catch (error) {\n logger.error('Error converting HTML to Markdown:', error);\n return html;\n }\n}\n","/*\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport interface Task<T> {\n (): Promise<T>;\n}\n\nexport class PromiseQueue {\n private queue: Task<any>[] = [];\n\n private concurrency: number;\n\n private running = 0;\n\n private results: any[] = [];\n\n constructor(concurrency = 1) {\n this.concurrency = concurrency;\n }\n\n add<T>(task: Task<T>): Promise<T> {\n return new Promise((resolve, reject) => {\n this.queue.push(async () => {\n try {\n const result = await task();\n resolve(result);\n return result;\n } catch (error) {\n reject(error);\n throw error;\n }\n });\n this.run();\n });\n }\n\n private async run() {\n if (this.running >= this.concurrency || this.queue.length === 0) {\n return;\n }\n\n this.running++;\n const task = this.queue.shift()!;\n\n try {\n const result = await task();\n this.results.push(result);\n } catch (error) {\n // Handle error if needed\n } finally {\n this.running--;\n this.run();\n }\n }\n\n async waitAll(): Promise<any[]> {\n while (this.running > 0 || this.queue.length > 0) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n return this.results;\n }\n}","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Page } from 'puppeteer-core';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Bing search engine adapter implementation.\n * Provides functionality to generate Bing search URLs and extract search results from Bing search pages.\n */\nexport class BingSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Bing search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Bing search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const searchParams = new URLSearchParams({\n q: `${\n options.excludeDomains && options.excludeDomains.length > 0\n ? `${options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')} `\n : ''\n }${query}`,\n count: `${options.count || 10}`,\n });\n\n return `https://www.bing.com/search?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Bing search page.\n *\n * @param window - The browser window object containing the loaded Bing search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n /**\n * Validates if a string is a properly formatted URL.\n *\n * @param url - The URL string to validate\n * @returns Boolean indicating if the URL is valid\n */\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n /**\n * Extracts the snippet text from a search result element\n * @param element - The search result element\n * @returns The extracted snippet text\n */\n const extractSnippet = (element: Element): string => {\n // Clone the element to avoid modifying the original DOM\n const clone = element.cloneNode(true) as Element;\n \n // Remove title elements (typically h2 tags in Bing)\n const titleElements = clone.querySelectorAll('h2');\n titleElements.forEach((el) => el.remove());\n\n // Remove any cite/URL elements\n const citeElements = clone.querySelectorAll('.b_attribution');\n citeElements.forEach((el) => el.remove());\n\n // Remove script and style elements\n const scriptElements = clone.querySelectorAll('script, style');\n scriptElements.forEach((el) => el.remove());\n\n // Get text content and remove duplicates\n const text = Array.from(clone.querySelectorAll('*'))\n .filter((node) => node.textContent?.trim())\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .reduce((acc: string[], curr) => {\n // Only add text if it's not already included in accumulated text\n if (\n !acc.some(\n (text) =>\n text.includes(curr as string) ||\n (curr as string).includes(text),\n )\n ) {\n acc.push(curr as string);\n }\n return acc;\n }, [])\n .join(' ')\n .trim()\n .replace(/\\s+/g, ' ');\n\n return text;\n };\n\n try {\n // Bing search results are in elements with class 'b_algo'\n const elements = document.querySelectorAll('.b_algo');\n elements.forEach((element) => {\n const titleEl = element.querySelector('h2');\n const urlEl = element.querySelector('h2 a');\n const url = urlEl?.getAttribute('href');\n const snippet = extractSnippet(element);\n\n if (!url || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n snippet,\n url,\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error('Error extracting search results from Bing:', error);\n throw error;\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#b_results', {\n timeout: timeout ?? 10000,\n });\n }\n}","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { Page } from '../../browser/index.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Baidu search engine adapter implementation.\n * Provides functionality to generate Baidu search URLs and extract search results from Baidu search pages.\n */\nexport class BaiduSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Baidu search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Baidu search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n // Baidu doesn't support excluding domains in the same way as Google\n // But we can add '-site:domain' to the query\n const excludeDomainsQuery =\n options.excludeDomains && options.excludeDomains.length > 0\n ? options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')\n : '';\n\n const searchParams = new URLSearchParams({\n wd: excludeDomainsQuery ? `${excludeDomainsQuery} ${query}` : query,\n rn: `${options.count || 10}`, // rn is the parameter for result count\n });\n\n return `https://www.baidu.com/s?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Baidu search page.\n *\n * @param window - The browser window object containing the loaded Baidu search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n try {\n // Baidu search results are in elements with class 'result'\n const elements = document.querySelectorAll('.result');\n elements.forEach((element) => {\n const titleEl = element.querySelector('.t a');\n const url = titleEl?.getAttribute('href');\n const snippetEl = element.querySelector('.c-span-last .content-right_2s-H4');\n\n if (!url) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n url, // Note: Baidu uses redirects, we'll need to follow them\n snippet: snippetEl?.textContent || '',\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error('Error extracting search results from Baidu:', error);\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#page', {\n timeout: timeout ?? 10000,\n });\n }\n}","import { Page } from '../../browser/index.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\nexport class SogouSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Sogou search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Sogou search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const { count = 10, excludeDomains = [] } = options;\n\n const excludeDomainsQuery =\n excludeDomains && excludeDomains.length > 0\n ? excludeDomains.map((domain) => `-site:${domain}`).join(' ')\n : '';\n\n const searchParams = new URLSearchParams({\n query: `${excludeDomainsQuery ? `${excludeDomainsQuery} ` : ''}${query}`,\n num: `${count}`,\n });\n\n return `https://www.sogou.com/web?${searchParams.toString()}`;\n }\n\n /**\n * !NOTE: This function runs in the context of the browser page, not Node.js\n * \n * Extract search results from Sogou\n * @param window - The window object\n * @returns Search results\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n const EndPoints = 'https://www.sogou.com';\n \n const SELECTOR = {\n results: '.results .vrwrap',\n resultTitle: '.vr-title',\n resultLink: '.vr-title > a',\n resultSnippet: ['.star-wiki', '.fz-mid', '.attribute-centent'],\n resultSnippetExcluded: ['.text-lightgray', '.zan-box', '.tag-website'],\n related: '#main .vrwrap.middle-better-hintBox .hint-mid',\n };\n\n try {\n const elements = document.querySelectorAll(SELECTOR.results);\n elements.forEach((element) => {\n const titleEl = element.querySelector(SELECTOR.resultTitle);\n let url = element.querySelector(SELECTOR.resultLink)?.getAttribute('href');\n\n const snippets = SELECTOR.resultSnippet.map((selector) => {\n // remove excluded elements\n SELECTOR.resultSnippetExcluded.forEach((excludedSelector) => {\n const el = element.querySelector(excludedSelector);\n el?.remove();\n });\n // get the text content of the element\n const el = element.querySelector(selector);\n return el?.textContent?.trim() || '';\n });\n\n if (!url?.includes('http')) url = `${EndPoints}${url}`;\n\n if (!url?.trim() || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent?.trim() || '',\n url,\n snippet: snippets.join(''),\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error('Error extracting search results from Sogou:', msg);\n throw error;\n }\n\n return links;\n }\n\n /**\n * Waits for Bing search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#pagebar_container', {\n timeout: timeout ?? 10000,\n });\n }\n}\n","/**\n * Copyright (c) 2025 Bytedance, Inc. and its affiliates.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport type { Page } from '../../browser/types.js';\nimport type { SearchEngineAdapter, SearchResult } from '../types.js';\n\n/**\n * Google search engine adapter implementation.\n * Provides functionality to generate Google search URLs and extract search results from Google search pages.\n */\nexport class GoogleSearchEngine implements SearchEngineAdapter {\n /**\n * Generates a Google search URL based on the provided query and options.\n *\n * @param query - The search query string\n * @param options - Search configuration options\n * @param options.count - Number of search results to request (default: 10)\n * @param options.excludeDomains - Array of domain names to exclude from search results\n * @returns Formatted Google search URL as a string\n */\n getSearchUrl(\n query: string,\n options: {\n count?: number;\n excludeDomains?: string[];\n },\n ): string {\n const searchParams = new URLSearchParams({\n q: `${\n options.excludeDomains && options.excludeDomains.length > 0\n ? `${options.excludeDomains.map((domain) => `-site:${domain}`).join(' ')} `\n : ''\n }${query}`,\n num: `${options.count || 10}`,\n });\n\n searchParams.set('udm', '14');\n return `https://www.google.com/search?${searchParams.toString()}`;\n }\n\n /**\n * Extracts search results from a Google search page.\n *\n * @param window - The browser window object containing the loaded Google search page\n * @returns Array of search results extracted from the page\n */\n extractSearchResults(window: Window): SearchResult[] {\n const links: SearchResult[] = [];\n const document = window.document;\n\n /**\n * Validates if a string is a properly formatted URL.\n *\n * @param url - The URL string to validate\n * @returns Boolean indicating if the URL is valid\n */\n const isValidUrl = (url: string) => {\n try {\n new URL(url);\n return true;\n } catch (error) {\n return false;\n }\n };\n\n /**\n * Extracts the snippet text from an element by cloning it and removing title elements\n *\n * @param element - The search result element\n * @returns The extracted snippet text\n */\n const extractSnippet = (element: Element): string => {\n // Clone the element to avoid modifying the original DOM\n const clone = element.cloneNode(true) as Element;\n\n // Remove title elements (typically h3 tags in Google)\n const titleElements = clone.querySelectorAll('h3');\n titleElements.forEach((el) => el.remove());\n\n // Remove any cite elements (showing the URL)\n const citeElements = clone.querySelectorAll('cite');\n citeElements.forEach((el) => el.remove());\n\n // Remove script and style elements\n const scriptElements = clone.querySelectorAll('script, style');\n scriptElements.forEach((el) => el.remove());\n\n // Get text content and remove duplicates\n const text = Array.from(clone.querySelectorAll('*'))\n .filter((node) => node.textContent?.trim())\n .map((node) => node.textContent?.trim())\n .filter(Boolean)\n .reduce((acc: string[], curr) => {\n // Only add text if it's not already included in accumulated text\n if (\n !acc.some(\n (text) =>\n text.includes(curr as string) ||\n (curr as string).includes(text),\n )\n ) {\n acc.push(curr as string);\n }\n return acc;\n }, [])\n .join(' ')\n .trim()\n .replace(/\\s+/g, ' ');\n\n return text;\n };\n\n try {\n // Google search results are contained in elements with class 'tF2Cxc'\n // It may change at any time\n const elements = document.querySelectorAll('.tF2Cxc');\n elements.forEach((element) => {\n const titleEl = element.querySelector('h3');\n const urlEl = element.querySelector('a');\n const url = urlEl?.getAttribute('href');\n\n // Extract snippet using the generic method\n const snippet = extractSnippet(element.parentElement || element);\n\n if (!url || !isValidUrl(url)) return;\n\n const item: SearchResult = {\n title: titleEl?.textContent || '',\n url,\n snippet,\n content: '',\n };\n\n if (!item.title || !item.url) return;\n\n links.push(item);\n });\n } catch (error) {\n console.error(error);\n }\n\n return links;\n }\n\n /**\n * Waits for Google search results to load completely.\n *\n * @param page - The Puppeteer page object\n * @returns Promise that resolves when search results are loaded\n */\n async waitForSearchResults(page: Page, timeout?: number): Promise<void> {\n await page.waitForSelector('#search', {\n timeout: timeout ?? 10000,\n });\n }\n}","import { BingSearchEngine } from './bing.js';\nimport { BaiduSearchEngine } from './baidu.js';\nimport type { LocalBrowserSearchEngine, SearchEngineAdapter } from '../types.js';\nimport { SogouSearchEngine } from './sogou.js';\nimport { GoogleSearchEngine } from './google.js';\n\n/**\n * Factory function to get the appropriate search engine adapter instance.\n *\n * @param engine - The search engine identifier ('sogou', 'bing', or 'baidu')\n * @returns An instance of the requested search engine adapter\n */\nexport function getSearchEngine(engine: LocalBrowserSearchEngine): SearchEngineAdapter {\n switch (engine) {\n case 'bing':\n return new BingSearchEngine();\n case 'baidu':\n return new BaiduSearchEngine();\n case 'sogou':\n return new SogouSearchEngine();\n case 'google':\n return new GoogleSearchEngine();\n default:\n return new BingSearchEngine();\n }\n}","import { ISearchRequestOptions, ISearchResponse, ISearchResponseResult } from '../interface.js';\nimport { BrowserSearch, LocalBrowserSearchEngine } from '../libs/browser-search/index.js';\nimport { ConsoleLogger } from '@agent-infra/logger';\n\nconst logger = new ConsoleLogger('[LocalSearch]');\n\nexport async function localSearch(options: ISearchRequestOptions): Promise<ISearchResponse> {\n const { query, limit = 10 } = options;\n let { engines = 'all' } = options;\n const browserSearch = new BrowserSearch({\n logger,\n browserOptions: {\n headless: true,\n },\n });\n\n if (engines === 'all') {\n engines = 'bing,google,baidu,sogou';\n }\n\n try {\n const engineList = engines.split(',');\n\n if (engineList.length === 0) {\n throw new Error('engines is required');\n }\n\n const results: ISearchResponseResult[] = [];\n\n for (const engine of engineList) {\n const res = await browserSearch.perform({\n query,\n count: limit,\n engine: engine as LocalBrowserSearchEngine,\n needVisitedUrls: false,\n });\n\n if (res.length > 0) {\n results.push(...res);\n break;\n }\n }\n\n logger.info(`Found ${results.length} results for ${query}`, results);\n\n return {\n results,\n success: true,\n };\n } catch (err: unknown) {\n const msg = err instanceof Error ? err.message : 'Local search error.';\n process.stdout.write(msg);\n throw err;\n } finally {\n await browserSearch.closeBrowser();\n }\n}","/**\n * The following tools are based on the Firecrawl MCP Server\n * https://github.com/mendableai/firecrawl-mcp-server\n */\n\nimport { Tool } from '@modelcontextprotocol/sdk/types.js';\n\n// tools definition\nexport const SEARCH_TOOL: Tool = {\n name: 'one_search',\n description:\n 'Search and retrieve content from web pages. ' +\n 'Returns SERP results by default (url, title, description).',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query string',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results to return (default: 10)',\n },\n language: {\n type: 'string',\n description: 'Language code for search results (default: auto)',\n },\n categories: {\n type: 'string',\n enum: [\n 'general',\n 'news',\n 'images',\n 'videos',\n 'it',\n 'science',\n 'map',\n 'music',\n 'files',\n 'social_media',\n ],\n description: 'Categories to search for (default: general)',\n },\n timeRange: {\n type: 'string',\n description: 'Time range for search results (default: all)',\n enum: [\n 'all',\n 'day',\n 'week',\n 'month',\n 'year',\n ],\n },\n },\n required: ['query'],\n },\n};\n\nexport const MAP_TOOL: Tool = {\n name: 'one_map',\n description:\n 'Discover URLs from a starting point. Can use both sitemap.xml and HTML link discovery.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'Starting URL for URL discovery',\n },\n search: {\n type: 'string',\n description: 'Optional search term to filter URLs',\n },\n ignoreSitemap: {\n type: 'boolean',\n description: 'Skip sitemap.xml discovery and only use HTML links',\n },\n sitemapOnly: {\n type: 'boolean',\n description: 'Only use sitemap.xml for discovery, ignore HTML links',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include URLs from subdomains in results',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of URLs to return',\n },\n },\n required: ['url'],\n },\n};\n\nexport const SCRAPE_TOOL: Tool = {\n name: 'one_scrape',\n description:\n 'Scrape a single webpage with advanced options for content extraction. ' +\n 'Supports various formats including markdown, HTML, and screenshots. ' +\n 'Can execute custom actions like clicking or scrolling before scraping.',\n inputSchema: {\n type: 'object',\n properties: {\n url: {\n type: 'string',\n description: 'The URL to scrape',\n },\n formats: {\n type: 'array',\n items: {\n type: 'string',\n enum: [\n 'markdown',\n 'html',\n 'rawHtml',\n 'screenshot',\n 'links',\n 'screenshot@fullPage',\n 'extract',\n ],\n },\n description: \"Content formats to extract (default: ['markdown'])\",\n },\n onlyMainContent: {\n type: 'boolean',\n description:\n 'Extract only the main content, filtering out navigation, footers, etc.',\n },\n includeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to specifically include in extraction',\n },\n excludeTags: {\n type: 'array',\n items: { type: 'string' },\n description: 'HTML tags to exclude from extraction',\n },\n waitFor: {\n type: 'number',\n description: 'Time in milliseconds to wait for dynamic content to load',\n },\n timeout: {\n type: 'number',\n description:\n 'Maximum time in milliseconds to wait for the page to load',\n },\n actions: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string',\n enum: [\n 'wait',\n 'click',\n 'screenshot',\n 'write',\n 'press',\n 'scroll',\n 'scrape',\n 'executeJavascript',\n ],\n description: 'Type of action to perform',\n },\n selector: {\n type: 'string',\n description: 'CSS selector for the target element',\n },\n milliseconds: {\n type: 'number',\n description: 'Time to wait in milliseconds (for wait action)',\n },\n text: {\n type: 'string',\n description: 'Text to write (for write action)',\n },\n key: {\n type: 'string',\n description: 'Key to press (for press action)',\n },\n direction: {\n type: 'string',\n enum: ['up', 'down'],\n description: 'Scroll direction',\n },\n script: {\n type: 'string',\n description: 'JavaScript code to execute',\n },\n fullPage: {\n type: 'boolean',\n description: 'Take full page screenshot',\n },\n },\n required: ['type'],\n },\n description: 'List of actions to perform before scraping',\n },\n extract: {\n type: 'object',\n properties: {\n schema: {\n type: 'object',\n description: 'Schema for structured data extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n prompt: {\n type: 'string',\n description: 'User prompt for LLM extraction',\n },\n },\n description: 'Configuration for structured data extraction',\n },\n mobile: {\n type: 'boolean',\n description: 'Use mobile viewport',\n },\n skipTlsVerification: {\n type: 'boolean',\n description: 'Skip TLS certificate verification',\n },\n removeBase64Images: {\n type: 'boolean',\n description: 'Remove base64 encoded images from output',\n },\n location: {\n type: 'object',\n properties: {\n country: {\n type: 'string',\n description: 'Country code for geolocation',\n },\n languages: {\n type: 'array',\n items: { type: 'string' },\n description: 'Language codes for content',\n },\n },\n description: 'Location settings for scraping',\n },\n },\n required: ['url'],\n },\n};\n\n\n\nexport const EXTRACT_TOOL: Tool = {\n name: 'one_extract',\n description:\n 'Extract structured information from web pages using LLM. ' +\n 'Supports both cloud AI and self-hosted LLM extraction.',\n inputSchema: {\n type: 'object',\n properties: {\n urls: {\n type: 'array',\n items: { type: 'string' },\n description: 'List of URLs to extract information from',\n },\n prompt: {\n type: 'string',\n description: 'Prompt for the LLM extraction',\n },\n systemPrompt: {\n type: 'string',\n description: 'System prompt for LLM extraction',\n },\n schema: {\n type: 'object',\n description: 'JSON schema for structured data extraction',\n },\n allowExternalLinks: {\n type: 'boolean',\n description: 'Allow extraction from external links',\n },\n enableWebSearch: {\n type: 'boolean',\n description: 'Enable web search for additional context',\n },\n includeSubdomains: {\n type: 'boolean',\n description: 'Include subdomains in extraction',\n },\n },\n required: ['urls'],\n },\n};\n"],"mappings":"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nB,CAAC,EAED,GAAIC,EAAI,OAAS,EAAG,CAClBF,EAAQ,KAAK,GAAGE,CAAG,EACnB,KACF,CACF,CAEA,OAAAX,GAAO,KAAK,SAASS,EAAQ,MAAM,gBAAgBN,CAAK,GAAIM,CAAO,EAE5D,CACL,QAAAA,EACA,QAAS,EACX,CACF,OAASG,EAAc,CACrB,IAAMC,EAAMD,aAAe,MAAQA,EAAI,QAAU,sBACjD,cAAQ,OAAO,MAAMC,CAAG,EAClBD,CACR,QAAE,CACA,MAAMN,EAAc,aAAa,CACnC,CACF,CChDO,IAAMQ,GAAoB,CAC/B,KAAM,aACN,YACE,yGAEF,YAAa,CACX,KAAM,SACN,WAAY,CACV,MAAO,CACL,KAAM,SACN,YAAa,qBACf,EACA,MAAO,CACL,KAAM,SACN,YAAa,mDACf,EACA,SAAU,CACR,KAAM,SACN,YAAa,kDACf,EACA,WAAY,CACV,KAAM,SACN,KAAM,CACJ,UACA,OACA,SACA,SACA,KACA,UACA,MACA,QACA,QACA,cACF,EACA,YAAa,6CACf,EACA,UAAW,CACT,KAAM,SACN,YAAa,+CACb,KAAM,CACJ,MACA,MACA,OACA,QACA,MACF,CACF,CACF,EACA,SAAU,CAAC,OAAO,CACpB,CACF,EAEaC,GAAiB,CAC5B,KAAM,UACN,YACE,yFACF,YAAa,CACX,KAAM,SACN,WAAY,CACV,IAAK,CACH,KAAM,SACN,YAAa,gCACf,EACA,OAAQ,CACN,KAAM,SACN,YAAa,qCACf,EACA,cAAe,CACb,KAAM,UACN,YAAa,oDACf,EACA,YAAa,CACX,KAAM,UACN,YAAa,uDACf,EACA,kBAAmB,CACjB,KAAM,UACN,YAAa,yCACf,EACA,MAAO,CACL,KAAM,SACN,YAAa,kCACf,CACF,EACA,SAAU,CAAC,KAAK,CAClB,CACF,EAEaC,GAAoB,CAC/B,KAAM,aACN,YACE,mNAGF,YAAa,CACX,KAAM,SACN,WAAY,CACV,IAAK,CACH,KAAM,SACN,YAAa,mBACf,EACA,QAAS,CACP,KAAM,QACN,MAAO,CACL,KAAM,SACN,KAAM,CACJ,WACA,OACA,UACA,aACA,QACA,sBACA,SACF,CACF,EACA,YAAa,oDACf,EACA,gBAAiB,CACf,KAAM,UACN,YACE,wEACJ,EACA,YAAa,CACX,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,iDACf,EACA,YAAa,CACX,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,sCACf,EACA,QAAS,CACP,KAAM,SACN,YAAa,0DACf,EACA,QAAS,CACP,KAAM,SACN,YACE,2DACJ,EACA,QAAS,CACP,KAAM,QACN,MAAO,CACL,KAAM,SACN,WAAY,CACV,KAAM,CACJ,KAAM,SACN,KAAM,CACJ,OACA,QACA,aACA,QACA,QACA,SACA,SACA,mBACF,EACA,YAAa,2BACf,EACA,SAAU,CACR,KAAM,SACN,YAAa,qCACf,EACA,aAAc,CACZ,KAAM,SACN,YAAa,gDACf,EACA,KAAM,CACJ,KAAM,SACN,YAAa,kCACf,EACA,IAAK,CACH,KAAM,SACN,YAAa,iCACf,EACA,UAAW,CACT,KAAM,SACN,KAAM,CAAC,KAAM,MAAM,EACnB,YAAa,kBACf,EACA,OAAQ,CACN,KAAM,SACN,YAAa,4BACf,EACA,SAAU,CACR,KAAM,UACN,YAAa,2BACf,CACF,EACA,SAAU,CAAC,MAAM,CACnB,EACA,YAAa,4CACf,EACA,QAAS,CACP,KAAM,SACN,WAAY,CACV,OAAQ,CACN,KAAM,SACN,YAAa,uCACf,EACA,aAAc,CACZ,KAAM,SACN,YAAa,kCACf,EACA,OAAQ,CACN,KAAM,SACN,YAAa,gCACf,CACF,EACA,YAAa,8CACf,EACA,OAAQ,CACN,KAAM,UACN,YAAa,qBACf,EACA,oBAAqB,CACnB,KAAM,UACN,YAAa,mCACf,EACA,mBAAoB,CAClB,KAAM,UACN,YAAa,0CACf,EACA,SAAU,CACR,KAAM,SACN,WAAY,CACV,QAAS,CACP,KAAM,SACN,YAAa,8BACf,EACA,UAAW,CACT,KAAM,QACN,MAAO,CAAE,KAAM,QAAS,EACxB,YAAa,4BACf,CACF,EACA,YAAa,gCACf,CACF,EACA,SAAU,CAAC,KAAK,CAClB,CACF,EAIaC,GAAqB,CACh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","names":["index_exports","__toCommonJS","import_server","import_types","import_stdio","bingSearch","options","query","limit","safeSearch","page","apiUrl","apiKey","language","bingSafeSearchOptions","searchOptions","queryParams","key","value","res","item","err","msg","DDG","import_async_retry","duckDuckGoSearch","options","query","timeout","safeSearch","retry","searchOptions","res","asyncRetry","result","error","msg","import_node_url","searxngSearch","params","query","page","limit","categories","engines","safeSearch","format","language","timeRange","timeout","apiKey","apiUrl","controller","timeoutId","config","endpoint","queryParams","url","headers","res","response","item","image","video","err","msg","import_core","tavilySearch","options","query","limit","categories","timeRange","apiKey","tvly","params","item","error","msg","import_puppeteer_core","fs","path","os","import_logger","BrowserFinder","logger","HOME_DIR","LOCAL_APP_DATA","name","platform","error","browser","b","result","browserName","profileInfo","profileName","info","executable","import_logger","BaseBrowser","options","target","page","error","url","pageFunction","pageFunctionParams","beforePageLoad","afterPageLoad","beforeSendResult","waitForOptions","_window","result","pages","i","puppeteer","LocalBrowser","BaseBrowser","BrowserFinder","options","executablePath","viewportWidth","viewportHeight","puppeteerLaunchOptions","error","puppeteer","READABILITY_SCRIPT","import_logger","import_turndown","import_turndown_plugin_gfm","import_logger","import_user_agents","parseUrl","url","shouldSkipDomain","parsed","hostname","applyStealthScripts","page","userAgent","UserAgent","originalQuery","parameters","interceptRequest","request","extractPageInformation","window","readabilityScript","Readability","document","el","article","content","title","toMarkdown","html","options","codeBlockStyle","headingStyle","emDelimiter","strongDelimiter","gfmExtension","turndown","Turndown","error","logger","PromiseQueue","concurrency","task","resolve","reject","result","error","BingSearchEngine","query","options","domain","window","links","document","isValidUrl","url","extractSnippet","element","clone","el","node","acc","curr","text","titleEl","snippet","item","error","page","timeout","BaiduSearchEngine","query","options","excludeDomainsQuery","domain","window","links","document","element","titleEl","url","snippetEl","item","error","page","timeout","SogouSearchEngine","query","options","count","excludeDomains","excludeDomainsQuery","domain","window","links","document","isValidUrl","url","EndPoints","SELECTOR","element","titleEl","snippets","selector","excludedSelector","item","error","msg","page","timeout","GoogleSearchEngine","query","options","searchParams","domain","window","links","document","isValidUrl","url","extractSnippet","element","clone","el","node","acc","curr","text","titleEl","snippet","item","error","page","timeout","getSearchEngine","engine","BingSearchEngine","BaiduSearchEngine","SogouSearchEngine","GoogleSearchEngine","BrowserSearch","config","LocalBrowser","options","queries","excludeDomains","count","engine","queue","PromiseQueue","visitedUrls","results","query","error","browser","searchEngine","getSearchEngine","url","links","page","interceptRequest","link","shouldSkipDomain","item","result","v","extractPageInformation","READABILITY_SCRIPT","content","toMarkdown","e","import_logger","logger","localSearch","options","query","limit","engines","browserSearch","BrowserSearch","engineList","results","engine","res","err","msg","SEARCH_TOOL","MAP_TOOL","SCRAPE_TOOL","EXTRACT_TOOL","import_firecrawl_js","import_dotenvx","import_duck_duck_scrape","dotenvx","SEARCH_API_URL","SEARCH_API_KEY","SEARCH_PROVIDER","SAFE_SEARCH","LIMIT","CATEGORIES","ENGINES","FORMAT","LANGUAGE","TIME_RANGE","DEFAULT_TIMEOUT","FIRECRAWL_API_KEY","FIRECRAWL_API_URL","firecrawl","FirecrawlApp","server","searchDefaultConfig","SEARCH_TOOL","EXTRACT_TOOL","SCRAPE_TOOL","MAP_TOOL","request","startTime","name","args","checkSearchArgs","results","success","processSearch","result","error","checkScrapeArgs","url","scrapeArgs","content","processScrape","checkMapArgs","processMapUrl","msg","params","categories","language","searxngSearch","tavilySearch","bingSearch","safeSearch","safeSearchOptions","duckDuckGoSearch","localSearch","res","runServer","transport"]}