Skip to content

Commit 1a43e5f

Browse files
committed
fix: adjust websearch tool to emphasize that it ISNT 2024, give more info as to current date
1 parent 46be47d commit 1a43e5f

File tree

2 files changed

+98
-89
lines changed

2 files changed

+98
-89
lines changed

packages/opencode/src/tool/websearch.ts

Lines changed: 95 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -36,109 +36,115 @@ interface McpSearchResponse {
3636
}
3737
}
3838

39-
export const WebSearchTool = Tool.define("websearch", {
40-
description: DESCRIPTION,
41-
parameters: z.object({
42-
query: z.string().describe("Websearch query"),
43-
numResults: z.number().optional().describe("Number of search results to return (default: 8)"),
44-
livecrawl: z
45-
.enum(["fallback", "preferred"])
46-
.optional()
47-
.describe(
48-
"Live crawl mode - 'fallback': use live crawling as backup if cached content unavailable, 'preferred': prioritize live crawling (default: 'fallback')",
49-
),
50-
type: z
51-
.enum(["auto", "fast", "deep"])
52-
.optional()
53-
.describe("Search type - 'auto': balanced search (default), 'fast': quick results, 'deep': comprehensive search"),
54-
contextMaxCharacters: z
55-
.number()
56-
.optional()
57-
.describe("Maximum characters for context string optimized for LLMs (default: 10000)"),
58-
}),
59-
async execute(params, ctx) {
60-
await ctx.ask({
61-
permission: "websearch",
62-
patterns: [params.query],
63-
always: ["*"],
64-
metadata: {
65-
query: params.query,
66-
numResults: params.numResults,
67-
livecrawl: params.livecrawl,
68-
type: params.type,
69-
contextMaxCharacters: params.contextMaxCharacters,
70-
},
71-
})
72-
73-
const searchRequest: McpSearchRequest = {
74-
jsonrpc: "2.0",
75-
id: 1,
76-
method: "tools/call",
77-
params: {
78-
name: "web_search_exa",
79-
arguments: {
39+
export const WebSearchTool = Tool.define("websearch", async () => {
40+
return {
41+
get description() {
42+
return DESCRIPTION.replace("{{date}}", new Date().toISOString().slice(0, 10))
43+
},
44+
parameters: z.object({
45+
query: z.string().describe("Websearch query"),
46+
numResults: z.number().optional().describe("Number of search results to return (default: 8)"),
47+
livecrawl: z
48+
.enum(["fallback", "preferred"])
49+
.optional()
50+
.describe(
51+
"Live crawl mode - 'fallback': use live crawling as backup if cached content unavailable, 'preferred': prioritize live crawling (default: 'fallback')",
52+
),
53+
type: z
54+
.enum(["auto", "fast", "deep"])
55+
.optional()
56+
.describe(
57+
"Search type - 'auto': balanced search (default), 'fast': quick results, 'deep': comprehensive search",
58+
),
59+
contextMaxCharacters: z
60+
.number()
61+
.optional()
62+
.describe("Maximum characters for context string optimized for LLMs (default: 10000)"),
63+
}),
64+
async execute(params, ctx) {
65+
await ctx.ask({
66+
permission: "websearch",
67+
patterns: [params.query],
68+
always: ["*"],
69+
metadata: {
8070
query: params.query,
81-
type: params.type || "auto",
82-
numResults: params.numResults || API_CONFIG.DEFAULT_NUM_RESULTS,
83-
livecrawl: params.livecrawl || "fallback",
71+
numResults: params.numResults,
72+
livecrawl: params.livecrawl,
73+
type: params.type,
8474
contextMaxCharacters: params.contextMaxCharacters,
8575
},
86-
},
87-
}
88-
89-
const controller = new AbortController()
90-
const timeoutId = setTimeout(() => controller.abort(), 25000)
76+
})
9177

92-
try {
93-
const headers: Record<string, string> = {
94-
accept: "application/json, text/event-stream",
95-
"content-type": "application/json",
78+
const searchRequest: McpSearchRequest = {
79+
jsonrpc: "2.0",
80+
id: 1,
81+
method: "tools/call",
82+
params: {
83+
name: "web_search_exa",
84+
arguments: {
85+
query: params.query,
86+
type: params.type || "auto",
87+
numResults: params.numResults || API_CONFIG.DEFAULT_NUM_RESULTS,
88+
livecrawl: params.livecrawl || "fallback",
89+
contextMaxCharacters: params.contextMaxCharacters,
90+
},
91+
},
9692
}
9793

98-
const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.SEARCH}`, {
99-
method: "POST",
100-
headers,
101-
body: JSON.stringify(searchRequest),
102-
signal: AbortSignal.any([controller.signal, ctx.abort]),
103-
})
94+
const controller = new AbortController()
95+
const timeoutId = setTimeout(() => controller.abort(), 25000)
10496

105-
clearTimeout(timeoutId)
97+
try {
98+
const headers: Record<string, string> = {
99+
accept: "application/json, text/event-stream",
100+
"content-type": "application/json",
101+
}
106102

107-
if (!response.ok) {
108-
const errorText = await response.text()
109-
throw new Error(`Search error (${response.status}): ${errorText}`)
110-
}
103+
const response = await fetch(`${API_CONFIG.BASE_URL}${API_CONFIG.ENDPOINTS.SEARCH}`, {
104+
method: "POST",
105+
headers,
106+
body: JSON.stringify(searchRequest),
107+
signal: AbortSignal.any([controller.signal, ctx.abort]),
108+
})
109+
110+
clearTimeout(timeoutId)
111+
112+
if (!response.ok) {
113+
const errorText = await response.text()
114+
throw new Error(`Search error (${response.status}): ${errorText}`)
115+
}
111116

112-
const responseText = await response.text()
117+
const responseText = await response.text()
113118

114-
// Parse SSE response
115-
const lines = responseText.split("\n")
116-
for (const line of lines) {
117-
if (line.startsWith("data: ")) {
118-
const data: McpSearchResponse = JSON.parse(line.substring(6))
119-
if (data.result && data.result.content && data.result.content.length > 0) {
120-
return {
121-
output: data.result.content[0].text,
122-
title: `Web search: ${params.query}`,
123-
metadata: {},
119+
// Parse SSE response
120+
const lines = responseText.split("\n")
121+
for (const line of lines) {
122+
if (line.startsWith("data: ")) {
123+
const data: McpSearchResponse = JSON.parse(line.substring(6))
124+
if (data.result && data.result.content && data.result.content.length > 0) {
125+
return {
126+
output: data.result.content[0].text,
127+
title: `Web search: ${params.query}`,
128+
metadata: {},
129+
}
124130
}
125131
}
126132
}
127-
}
128133

129-
return {
130-
output: "No search results found. Please try a different query.",
131-
title: `Web search: ${params.query}`,
132-
metadata: {},
133-
}
134-
} catch (error) {
135-
clearTimeout(timeoutId)
134+
return {
135+
output: "No search results found. Please try a different query.",
136+
title: `Web search: ${params.query}`,
137+
metadata: {},
138+
}
139+
} catch (error) {
140+
clearTimeout(timeoutId)
136141

137-
if (error instanceof Error && error.name === "AbortError") {
138-
throw new Error("Search request timed out")
139-
}
142+
if (error instanceof Error && error.name === "AbortError") {
143+
throw new Error("Search request timed out")
144+
}
140145

141-
throw error
142-
}
143-
},
146+
throw error
147+
}
148+
},
149+
}
144150
})

packages/opencode/src/tool/websearch.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@ Usage notes:
99
- Search types: 'auto' (balanced), 'fast' (quick results), 'deep' (comprehensive search)
1010
- Configurable context length for optimal LLM integration
1111
- Domain filtering and advanced search options available
12+
13+
Today's date is {{date}}. You MUST use this year when searching for recent information or current events
14+
- Example: If today is 2025-07-15 and the user asks for "latest AI news", search for "AI news 2025", NOT "AI news 2024"

0 commit comments

Comments
 (0)