diff options
Diffstat (limited to 'packages/tool-web-search/src/tool.ts')
| -rw-r--r-- | packages/tool-web-search/src/tool.ts | 216 |
1 files changed, 108 insertions, 108 deletions
diff --git a/packages/tool-web-search/src/tool.ts b/packages/tool-web-search/src/tool.ts index 751278d..b2e84fe 100644 --- a/packages/tool-web-search/src/tool.ts +++ b/packages/tool-web-search/src/tool.ts @@ -10,11 +10,11 @@ import type { ToolContract, ToolExecuteContext, ToolResult } from "@dispatch/kernel"; import type { FirecrawlClient } from "./client.js"; import { - formatCrawlResults, - formatMapResults, - formatScrapeResult, - formatSearchResults, - truncateOutput, + formatCrawlResults, + formatMapResults, + formatScrapeResult, + formatSearchResults, + truncateOutput, } from "./format.js"; import type { ValidatedArgs } from "./validate.js"; import { validateArgs } from "./validate.js"; @@ -22,51 +22,51 @@ import { validateArgs } from "./validate.js"; const OUTPUT_CAP = 50_000; export interface WebSearchToolDeps { - readonly client: FirecrawlClient; - readonly outputCap?: number; + readonly client: FirecrawlClient; + readonly outputCap?: number; } /** Dispatch validated args to the right client method and format the result. */ async function runMode( - validated: ValidatedArgs, - client: FirecrawlClient, - signal: AbortSignal, + validated: ValidatedArgs, + client: FirecrawlClient, + signal: AbortSignal, ): Promise<string> { - switch (validated.mode) { - case "search": { - const hits = await client.search( - { - query: validated.query, - limit: validated.limit, - ...(validated.scrape - ? { scrapeOptions: { formats: ["markdown"], onlyMainContent: true } } - : {}), - ...(validated.lang !== undefined ? { lang: validated.lang } : {}), - ...(validated.country !== undefined ? { country: validated.country } : {}), - }, - signal, - ); - return formatSearchResults(hits); - } - case "scrape": { - const result = await client.scrape( - { url: validated.url, formats: [validated.format] }, - signal, - ); - return formatScrapeResult(result); - } - case "crawl": { - const pages = await client.crawl( - { url: validated.url, limit: validated.limit, formats: [validated.format] }, - signal, - ); - return formatCrawlResults(pages); - } - case "map": { - const links = await client.map(validated.url, signal); - return formatMapResults(links); - } - } + switch (validated.mode) { + case "search": { + const hits = await client.search( + { + query: validated.query, + limit: validated.limit, + ...(validated.scrape + ? { scrapeOptions: { formats: ["markdown"], onlyMainContent: true } } + : {}), + ...(validated.lang !== undefined ? { lang: validated.lang } : {}), + ...(validated.country !== undefined ? { country: validated.country } : {}), + }, + signal, + ); + return formatSearchResults(hits); + } + case "scrape": { + const result = await client.scrape( + { url: validated.url, formats: [validated.format] }, + signal, + ); + return formatScrapeResult(result); + } + case "crawl": { + const pages = await client.crawl( + { url: validated.url, limit: validated.limit, formats: [validated.format] }, + signal, + ); + return formatCrawlResults(pages); + } + case "map": { + const links = await client.map(validated.url, signal); + return formatMapResults(links); + } + } } /** @@ -75,68 +75,68 @@ async function runMode( * is declared on the extension manifest (not the tool contract). */ export function createWebSearchTool(deps: WebSearchToolDeps): ToolContract { - const client = deps.client; - const cap = deps.outputCap ?? OUTPUT_CAP; + const client = deps.client; + const cap = deps.outputCap ?? OUTPUT_CAP; - return { - name: "web_search", - description: - "Access the web via a self-hosted Firecrawl instance. Supports search, " + - "single-page scrape, site crawling, and sitemap discovery.", - parameters: { - type: "object", - properties: { - query: { type: "string", description: "The search query (search mode)." }, - url: { type: "string", description: "A URL to scrape, crawl, or map." }, - mode: { - type: "string", - enum: ["search", "scrape", "crawl", "map"], - description: - "Operation mode. 'search' (default when query present), 'scrape' " + - "(default when url present), 'crawl' (recursively scrape pages from a site), " + - "'map' (discover URLs on a site).", - }, - limit: { - type: "number", - description: "Max results. Search: default 7, max 10. Crawl: default 3, max 10.", - }, - scrape: { - type: "boolean", - description: "When searching, also scrape full markdown content of each result page.", - }, - lang: { - type: "string", - description: 'Language code to filter search results (e.g. "en", "ja").', - }, - country: { - type: "string", - description: 'Country code to filter search results (e.g. "us", "jp").', - }, - format: { - type: "string", - enum: ["markdown", "text", "html"], - description: "Format for scrape/crawl output (default: markdown).", - }, - }, - }, - concurrencySafe: true, - async execute(args: unknown, ctx: ToolExecuteContext): Promise<ToolResult> { - const validated = validateArgs(args); - if ("error" in validated) { - return { content: validated.error, isError: true }; - } - const span = ctx.log.span("web_search.execute", { mode: validated.mode }); - try { - const output = await runMode(validated, client, ctx.signal); - span.end(); - return { content: truncateOutput(output, cap) }; - } catch (err: unknown) { - span.end({ err }); - return { - content: `Error: ${err instanceof Error ? err.message : String(err)}`, - isError: true, - }; - } - }, - }; + return { + name: "web_search", + description: + "Access the web via a self-hosted Firecrawl instance. Supports search, " + + "single-page scrape, site crawling, and sitemap discovery.", + parameters: { + type: "object", + properties: { + query: { type: "string", description: "The search query (search mode)." }, + url: { type: "string", description: "A URL to scrape, crawl, or map." }, + mode: { + type: "string", + enum: ["search", "scrape", "crawl", "map"], + description: + "Operation mode. 'search' (default when query present), 'scrape' " + + "(default when url present), 'crawl' (recursively scrape pages from a site), " + + "'map' (discover URLs on a site).", + }, + limit: { + type: "number", + description: "Max results. Search: default 7, max 10. Crawl: default 3, max 10.", + }, + scrape: { + type: "boolean", + description: "When searching, also scrape full markdown content of each result page.", + }, + lang: { + type: "string", + description: 'Language code to filter search results (e.g. "en", "ja").', + }, + country: { + type: "string", + description: 'Country code to filter search results (e.g. "us", "jp").', + }, + format: { + type: "string", + enum: ["markdown", "text", "html"], + description: "Format for scrape/crawl output (default: markdown).", + }, + }, + }, + concurrencySafe: true, + async execute(args: unknown, ctx: ToolExecuteContext): Promise<ToolResult> { + const validated = validateArgs(args); + if ("error" in validated) { + return { content: validated.error, isError: true }; + } + const span = ctx.log.span("web_search.execute", { mode: validated.mode }); + try { + const output = await runMode(validated, client, ctx.signal); + span.end(); + return { content: truncateOutput(output, cap) }; + } catch (err: unknown) { + span.end({ err }); + return { + content: `Error: ${err instanceof Error ? err.message : String(err)}`, + isError: true, + }; + } + }, + }; } |
