fix(tool-web): bound HTML conversion work

This commit is contained in:
Tianyi Cui
2026-07-27 16:40:02 +08:00
parent ae18216199
commit 9801a0d102
11 changed files with 314 additions and 100 deletions

View File

@@ -13,7 +13,7 @@ import { applyWebSearchTool, WEB_SEARCH_MAX_RESULTS } from './search.ts'
import { applyWebFetchTool } from './fetch.ts'
export { WEB_SEARCH_MAX_RESULTS, applyWebSearchTool, formatSearchOutput, parseSearchArgs, presentSearchCall } from './search.ts'
export { applyWebFetchTool, formatFetchOutput, htmlNestingDepth, parseFetchArgs, presentFetchCall, renderBody } from './fetch.ts'
export { applyWebFetchTool, formatFetchOutput, parseFetchArgs, presentFetchCall } from './fetch.ts'
/** Cordis plugin name used by loader diagnostics. */
export const name = 'tool-web'
@@ -25,11 +25,9 @@ export const inject = ['tools', 'web', 'systemPrompt']
export const DEFAULT_WEB_TOOL_TIMEOUT_MS = 30_000
/**
* Default cap on one `web_fetch` output's characters. Markdown escaping can
* roughly double converted HTML, so this sits at 2× the local provider's
* default 100,000-char body cap: it never cuts what that composition's
* provider bound already admits, while restoring a model-context bound for
* providers with larger or absent body caps.
* Default cap on one `web_fetch` output and on source characters converted
* synchronously. This leaves headroom above the local provider's default
* 100,000-character body cap while bounding custom providers and rendered output.
*/
export const DEFAULT_FETCH_MAX_OUTPUT_CHARS = 200_000
@@ -45,7 +43,7 @@ export interface Config {
fetchTimeoutMs?: number
/** Cooperative timeout budget (ms) for `web_search`. Defaults to 30000. */
searchTimeoutMs?: number
/** Cap on one `web_fetch` output's characters (header, rendered body, and footer). Defaults to 200000. */
/** Cap on source characters converted and complete `web_fetch` output characters. Defaults to 200000. */
fetchMaxOutputChars?: number
}
@@ -61,7 +59,7 @@ export const Config: z<Config> = z.object({
/** The shape after schemastery applies its defaults to every field. */
type ResolvedConfig = Required<Config>
/** The result cap must be a positive integer (it bounds a provider's source list). */
/** Configured count, timeout, and character caps must be positive integers. */
function assertPositiveInteger(name: string, value: number): void {
if (!Number.isInteger(value) || value < 1) {
throw new Error(`tool-web: ${name} must be a positive integer`)