From 01fd010a0e9dc619db7fe736cf039da49ae10969 Mon Sep 17 00:00:00 2001 From: paisley <8197966+su8su@users.noreply.github.com> Date: Fri, 24 Apr 2026 14:15:47 +0800 Subject: [PATCH] fix(browser): soften aggressive retry hint and add anti-hallucination prompts (#910) --- package.json | 1 + resources/context/AGENTS.clawx.md | 2 ++ resources/context/TOOLS.clawx.md | 2 ++ scripts/bundle-openclaw.mjs | 36 +++++++++++++++++++++ scripts/patch-browser-hint.mjs | 53 +++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 scripts/patch-browser-hint.mjs diff --git a/package.json b/package.json index a39e88f..d1860f8 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "license": "MIT", "private": true, "scripts": { + "postinstall": "node scripts/patch-browser-hint.mjs", "init": "pnpm install && pnpm run uv:download", "predev": "node scripts/generate-ext-bridge.mjs && zx scripts/prepare-preinstalled-skills-dev.mjs", "dev": "vite", diff --git a/resources/context/AGENTS.clawx.md b/resources/context/AGENTS.clawx.md index e62b868..426e695 100644 --- a/resources/context/AGENTS.clawx.md +++ b/resources/context/AGENTS.clawx.md @@ -1,3 +1,5 @@ ## ClawX Environment You are ClawX, a desktop AI assistant application based on OpenClaw. See TOOLS.md for ClawX-specific tool notes (uv, browser automation, etc.). + +**Tool Usage Rule**: You have access to real, working tools (browser, shell, file operations, etc.). Before telling the user "I can't do that" or "I don't have access to that tool", **always check your available tools and attempt the action first**. Only report inability after receiving an actual error from the tool. Do not refuse based on assumptions from your training data. diff --git a/resources/context/TOOLS.clawx.md b/resources/context/TOOLS.clawx.md index bb48656..63e7398 100644 --- a/resources/context/TOOLS.clawx.md +++ b/resources/context/TOOLS.clawx.md @@ -11,3 +11,5 @@ - Flow: `action="start"` → `action="snapshot"` (see page + get element refs like `e12`) → `action="act"` (click/type using refs). - Open new tabs: `action="open"` with `targetUrl`. - To just open a URL for the user to view, use `shell:openExternal` instead. +- If a browser action fails, transient errors (timeout, network) can often be resolved by retrying once or navigating to a different URL. +- When asked to search, look up, or interact with a web page, use the browser tool. Do not substitute with guesses or training data when real-time web access is requested. diff --git a/scripts/bundle-openclaw.mjs b/scripts/bundle-openclaw.mjs index 838a503..bb17683 100644 --- a/scripts/bundle-openclaw.mjs +++ b/scripts/bundle-openclaw.mjs @@ -789,6 +789,42 @@ function patchBundledRuntime(outputDir) { if (ptyCount > 0) { echo` 🩹 Patched ${ptyCount} bundled PTY site(s)`; } + + // --- Browser tool hint patch --- + // OpenClaw's BROWSER_TOOL_MODEL_HINT tells the model "Do NOT retry the + // browser tool — it will keep failing" after ANY error, causing the model + // to permanently refuse browser usage even on transient failures. + // Replace with a gentler hint that allows retries on transient errors. + const ORIGINAL_HINT = + 'Do NOT retry the browser tool \u2014 it will keep failing. Use an alternative approach or inform the user that the browser is currently unavailable.'; + const PATCHED_HINT = + 'If this was a transient error (timeout, network), you may retry once. If the same error persists after retry, try an alternative approach and let the user know.'; + const ORIGINAL_SHORT = 'Do NOT retry the browser tool.'; + const PATCHED_SHORT = 'You may retry once if this was a transient error.'; + + const distDir = path.join(outputDir, 'dist'); + let hintCount = 0; + if (fs.existsSync(distDir)) { + for (const file of fs.readdirSync(distDir)) { + if (!file.endsWith('.js')) continue; + const filePath = path.join(distDir, file); + try { + const content = fs.readFileSync(filePath, 'utf8'); + if (!content.includes(ORIGINAL_HINT) && !content.includes(ORIGINAL_SHORT)) continue; + const patched = content + .replaceAll(ORIGINAL_HINT, PATCHED_HINT) + .replaceAll(ORIGINAL_SHORT, PATCHED_SHORT); + if (patched !== content) { + fs.writeFileSync(filePath, patched, 'utf8'); + hintCount++; + } + } catch { /* skip on error */ } + } + } + + if (hintCount > 0) { + echo` 🩹 Patched ${hintCount} browser tool hint(s) to allow transient error retry`; + } } patchBrokenModules(outputNodeModules); diff --git a/scripts/patch-browser-hint.mjs b/scripts/patch-browser-hint.mjs new file mode 100644 index 0000000..1fed871 --- /dev/null +++ b/scripts/patch-browser-hint.mjs @@ -0,0 +1,53 @@ +#!/usr/bin/env node +/** + * Patch OpenClaw's BROWSER_TOOL_MODEL_HINT to allow retries on transient errors. + * + * The original hint ("Do NOT retry the browser tool — it will keep failing") + * causes models to permanently refuse browser usage after a single transient error. + * + * This runs as postinstall to patch node_modules for dev mode. + * Production builds are separately patched in bundle-openclaw.mjs. + */ + +import { readFileSync, writeFileSync, readdirSync } from 'fs'; +import { join } from 'path'; + +const REPLACEMENTS = [ + [ + 'Do NOT retry the browser tool \u2014 it will keep failing. Use an alternative approach or inform the user that the browser is currently unavailable.', + 'If this was a transient error (timeout, network), you may retry once. If the same error persists after retry, try an alternative approach and let the user know.', + ], + [ + 'Do NOT retry the browser tool.', + 'You may retry once if this was a transient error.', + ], +]; + +const distDir = join(process.cwd(), 'node_modules', 'openclaw', 'dist'); + +let patchedCount = 0; +try { + for (const file of readdirSync(distDir)) { + if (!file.endsWith('.js')) continue; + const filePath = join(distDir, file); + let content = readFileSync(filePath, 'utf-8'); + let changed = false; + for (const [search, replace] of REPLACEMENTS) { + if (content.includes(search)) { + content = content.replaceAll(search, replace); + changed = true; + } + } + if (changed) { + writeFileSync(filePath, content, 'utf-8'); + console.log(`[patch-browser-hint] Patched: ${file}`); + patchedCount++; + } + } +} catch { + // openclaw not installed yet or dist not found — skip silently +} + +if (patchedCount > 0) { + console.log(`[patch-browser-hint] Done. Patched ${patchedCount} file(s).`); +}