77 lines
2.5 KiB
TypeScript
77 lines
2.5 KiB
TypeScript
import z from "zod"
|
|
import { Effect } from "effect"
|
|
import { HttpClient } from "effect/unstable/http"
|
|
import { Tool } from "./tool"
|
|
import * as McpExa from "./mcp-exa"
|
|
import DESCRIPTION from "./websearch.txt"
|
|
|
|
const Parameters = z.object({
|
|
query: z.string().describe("Websearch query"),
|
|
numResults: z.number().optional().describe("Number of search results to return (default: 8)"),
|
|
livecrawl: z
|
|
.enum(["fallback", "preferred"])
|
|
.optional()
|
|
.describe(
|
|
"Live crawl mode - 'fallback': use live crawling as backup if cached content unavailable, 'preferred': prioritize live crawling (default: 'fallback')",
|
|
),
|
|
type: z
|
|
.enum(["auto", "fast", "deep"])
|
|
.optional()
|
|
.describe("Search type - 'auto': balanced search (default), 'fast': quick results, 'deep': comprehensive search"),
|
|
contextMaxCharacters: z
|
|
.number()
|
|
.optional()
|
|
.describe("Maximum characters for context string optimized for LLMs (default: 10000)"),
|
|
})
|
|
|
|
export const WebSearchTool = Tool.defineEffect(
|
|
"websearch",
|
|
Effect.gen(function* () {
|
|
const http = yield* HttpClient.HttpClient
|
|
|
|
return {
|
|
get description() {
|
|
return DESCRIPTION.replace("{{year}}", new Date().getFullYear().toString())
|
|
},
|
|
parameters: Parameters,
|
|
execute: (params: z.infer<typeof Parameters>, ctx: Tool.Context) =>
|
|
Effect.gen(function* () {
|
|
yield* Effect.promise(() =>
|
|
ctx.ask({
|
|
permission: "websearch",
|
|
patterns: [params.query],
|
|
always: ["*"],
|
|
metadata: {
|
|
query: params.query,
|
|
numResults: params.numResults,
|
|
livecrawl: params.livecrawl,
|
|
type: params.type,
|
|
contextMaxCharacters: params.contextMaxCharacters,
|
|
},
|
|
}),
|
|
)
|
|
|
|
const result = yield* McpExa.call(
|
|
http,
|
|
"web_search_exa",
|
|
McpExa.SearchArgs,
|
|
{
|
|
query: params.query,
|
|
type: params.type || "auto",
|
|
numResults: params.numResults || 8,
|
|
livecrawl: params.livecrawl || "fallback",
|
|
contextMaxCharacters: params.contextMaxCharacters,
|
|
},
|
|
"25 seconds",
|
|
)
|
|
|
|
return {
|
|
output: result ?? "No search results found. Please try a different query.",
|
|
title: `Web search: ${params.query}`,
|
|
metadata: {},
|
|
}
|
|
}).pipe(Effect.runPromise),
|
|
}
|
|
}),
|
|
)
|