Skip to content

Commit a4da1ca

Browse files
committed
fix: truncate webfetch response to MAX_TOKENS
1 parent 31dd9fd commit a4da1ca

File tree

1 file changed

+29
-32
lines changed

1 file changed

+29
-32
lines changed

packages/opencode/src/tool/webfetch.ts

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ import z from "zod"
22
import { Tool } from "./tool"
33
import TurndownService from "turndown"
44
import DESCRIPTION from "./webfetch.txt"
5+
import { Token } from "../util/token"
56

67
const MAX_RESPONSE_SIZE = 5 * 1024 * 1024 // 5MB
8+
const MAX_TOKENS = 50_000 // Maximum tokens to return (to avoid exceeding budget)
79
const DEFAULT_TIMEOUT = 30 * 1000 // 30 seconds
810
const MAX_TIMEOUT = 120 * 1000 // 2 minutes
911

@@ -89,50 +91,45 @@ export const WebFetchTool = Tool.define("webfetch", {
8991
const title = `${params.url} (${contentType})`
9092

9193
// Handle content based on requested format and actual content type
94+
let output = ""
9295
switch (params.format) {
9396
case "markdown":
9497
if (contentType.includes("text/html")) {
95-
const markdown = convertHTMLToMarkdown(content)
96-
return {
97-
output: markdown,
98-
title,
99-
metadata: {},
100-
}
101-
}
102-
return {
103-
output: content,
104-
title,
105-
metadata: {},
98+
output = convertHTMLToMarkdown(content)
99+
} else {
100+
output = content
106101
}
102+
break
107103

108104
case "text":
109105
if (contentType.includes("text/html")) {
110-
const text = await extractTextFromHTML(content)
111-
return {
112-
output: text,
113-
title,
114-
metadata: {},
115-
}
116-
}
117-
return {
118-
output: content,
119-
title,
120-
metadata: {},
106+
output = await extractTextFromHTML(content)
107+
} else {
108+
output = content
121109
}
110+
break
122111

123112
case "html":
124-
return {
125-
output: content,
126-
title,
127-
metadata: {},
128-
}
113+
output = content
114+
break
129115

130116
default:
131-
return {
132-
output: content,
133-
title,
134-
metadata: {},
135-
}
117+
output = content
118+
}
119+
120+
// Truncate if exceeds token limit
121+
const tokenCount = Token.estimate(output)
122+
if (tokenCount > MAX_TOKENS) {
123+
const charsPerToken = 4
124+
const maxChars = MAX_TOKENS * charsPerToken
125+
output = output.slice(0, maxChars)
126+
output += `\n\n[Content truncated: Response was ~${tokenCount.toLocaleString()} tokens, truncated to ${MAX_TOKENS.toLocaleString()} tokens to avoid exceeding budget]`
127+
}
128+
129+
return {
130+
output,
131+
title,
132+
metadata: {},
136133
}
137134
},
138135
})

0 commit comments

Comments
 (0)