summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAiden Cline <[email protected]>2026-01-15 20:50:18 -0600
committerAiden Cline <[email protected]>2026-01-15 20:50:22 -0600
commit1a43e5fe87e31abe062a006742df6c421f98f777 (patch)
tree8124a1056eb813e868c2ed9caeb381ae950d6042
parent46be47d0bea0302ad9fb3005f4a0fbbe73c0f325 (diff)
downloadopencode-1a43e5fe87e31abe062a006742df6c421f98f777.tar.gz
opencode-1a43e5fe87e31abe062a006742df6c421f98f777.zip
fix: adjust websearch tool to emphasize that it ISNT 2024, give more info as to current date
-rw-r--r--packages/opencode/src/tool/websearch.ts184
-rw-r--r--packages/opencode/src/tool/websearch.txt3
2 files changed, 98 insertions, 89 deletions
diff --git a/packages/opencode/src/tool/websearch.ts b/packages/opencode/src/tool/websearch.ts
index f6df36f10..9cc6af72d 100644
--- a/packages/opencode/src/tool/websearch.ts
+++ b/packages/opencode/src/tool/websearch.ts
@@ -36,109 +36,115 @@ interface McpSearchResponse {
}
}
-export const WebSearchTool = Tool.define("websearch", {
- description: DESCRIPTION,
- 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)"),
- }),
- async execute(params, ctx) {
- await 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 searchRequest: McpSearchRequest = {
- jsonrpc: "2.0",
- id: 1,
- method: "tools/call",
- params: {
- name: "web_search_exa",
- arguments: {
+export const WebSearchTool = Tool.define("websearch", async () => {
+ return {
+ get description() {
+ return DESCRIPTION.replace("{{date}}", new Date().toISOString().slice(0, 10))
+ },
+ 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)"),
+ }),
+ async execute(params, ctx) {
+ await ctx.ask({
+ permission: "websearch",
+ patterns: [params.query],
+ always: ["*"],
+ metadata: {
query: params.query,
- type: params.type || "auto",
- numResults: params.numResults || API_CONFIG.DEFAULT_NUM_RESULTS,
- livecrawl: params.livecrawl || "fallback",
+ numResults: params.numResults,
+ livecrawl: params.livecrawl,
+ type: params.type,
contextMaxCharacters: params.contextMaxCharacters,
},
- },
- }
-
- const controller = new AbortController()
- const timeoutId = setTimeout(() => controller.abort(), 25000)
+ })
- try {
- const headers: Record<string, string> = {
- accept: "application/json, text/event-stream",
- "content-type": "application/json",
+ const searchRequest: McpSearchRequest = {
+ jsonrpc: "2.0",
+ id: 1,
+ method: "tools/call",
+ params: {
+ name: "web_search_exa",
+ arguments: {
+ query: params.query,
+ type: params.type || "auto",
+ numResults: params.numResults || API_CONFIG.DEFAULT_NUM_RESULTS,
+ livecrawl: params.livecrawl || "fallback",
+ contextMaxCharacters: params.contextMaxCharacters,
+ },
+ },
}
- const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.SEARCH}`, {
- method: "POST",
- headers,
- body: JSON.stringify(searchRequest),
- signal: AbortSignal.any([controller.signal, ctx.abort]),
- })
+ const controller = new AbortController()
+ const timeoutId = setTimeout(() => controller.abort(), 25000)
- clearTimeout(timeoutId)
+ try {
+ const headers: Record<string, string> = {
+ accept: "application/json, text/event-stream",
+ "content-type": "application/json",
+ }
- if (!response.ok) {
- const errorText = await response.text()
- throw new Error(`Search error (${response.status}): ${errorText}`)
- }
+ const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.SEARCH}`, {
+ method: "POST",
+ headers,
+ body: JSON.stringify(searchRequest),
+ signal: AbortSignal.any([controller.signal, ctx.abort]),
+ })
+
+ clearTimeout(timeoutId)
+
+ if (!response.ok) {
+ const errorText = await response.text()
+ throw new Error(`Search error (${response.status}): ${errorText}`)
+ }
- const responseText = await response.text()
+ const responseText = await response.text()
- // Parse SSE response
- const lines = responseText.split("\n")
- for (const line of lines) {
- if (line.startsWith("data: ")) {
- const data: McpSearchResponse = JSON.parse(line.substring(6))
- if (data.result && data.result.content && data.result.content.length > 0) {
- return {
- output: data.result.content[0].text,
- title: `Web search: ${params.query}`,
- metadata: {},
+ // Parse SSE response
+ const lines = responseText.split("\n")
+ for (const line of lines) {
+ if (line.startsWith("data: ")) {
+ const data: McpSearchResponse = JSON.parse(line.substring(6))
+ if (data.result && data.result.content && data.result.content.length > 0) {
+ return {
+ output: data.result.content[0].text,
+ title: `Web search: ${params.query}`,
+ metadata: {},
+ }
}
}
}
- }
- return {
- output: "No search results found. Please try a different query.",
- title: `Web search: ${params.query}`,
- metadata: {},
- }
- } catch (error) {
- clearTimeout(timeoutId)
+ return {
+ output: "No search results found. Please try a different query.",
+ title: `Web search: ${params.query}`,
+ metadata: {},
+ }
+ } catch (error) {
+ clearTimeout(timeoutId)
- if (error instanceof Error && error.name === "AbortError") {
- throw new Error("Search request timed out")
- }
+ if (error instanceof Error && error.name === "AbortError") {
+ throw new Error("Search request timed out")
+ }
- throw error
- }
- },
+ throw error
+ }
+ },
+ }
})
diff --git a/packages/opencode/src/tool/websearch.txt b/packages/opencode/src/tool/websearch.txt
index 22427e246..657ac7458 100644
--- a/packages/opencode/src/tool/websearch.txt
+++ b/packages/opencode/src/tool/websearch.txt
@@ -9,3 +9,6 @@ Usage notes:
- Search types: 'auto' (balanced), 'fast' (quick results), 'deep' (comprehensive search)
- Configurable context length for optimal LLM integration
- Domain filtering and advanced search options available
+
+Today's date is {{date}}. You MUST use this year when searching for recent information or current events
+- Example: If today is 2025-07-15 and the user asks for "latest AI news", search for "AI news 2025", NOT "AI news 2024"