fix(vault): make browser_vault_fill work on the default Browser Use backend
On the default backend (browser.backend unset → browser_exec) the vault tools were advertised but could never fill: the CDP supervisor that carries the secret-bearing eval is started only by the built-in browser_* session path, so _eval_js_secret failed closed with supervisor_required and the origin pre-check fell back to an agent-browser CLI eval against a browser browser_exec never touched. - browser_exec now attaches SUPERVISOR_REGISTRY to the CDP endpoint it just routed the harness to (BU_CDP_WS/BU_CDP_URL), so the fill talks to the SAME browser over the same secret-capable WebSocket. BU direct-cloud (BU_AUTOSPAWN) exposes no endpoint and keeps the supervisor_required refusal. - CDPSupervisor.focus_page(origin, accept=<js>) (used by browser_vault_fill, next commits) re-attaches the page session to the open tab on the item's origin whose DOM holds the form being filled (browser_exec opens its own tabs; the supervisor's initial attach picks the first page target, which is chrome://new-tab-page). browser_vault_fill uses it before the origin pre-check with a per-kind probe (password input / card fields / address fields). Live: evals/vault_fill_live_e2e.py drives the real browser_exec tool against Hermes' packaged Chromium with the login page in the third tab; A/B with the attach line disabled fails at "did not attach a supervisor", enabled fills the password into the /login tab and card fields into the /checkout tab with every model-facing read scrubbed. Also: browser_vault_list/fill described the workflow as "type the identifier with fill_input", a helper that exists only inside browser_exec code (toolset browser-use) and is a ghost on the built-in stack. model_tools._rewrite_browser_vault substitutes the concrete name from the session's actual tool set (`fill_input` inside browser_exec, or browser_type), the same dynamic cross-reference pattern browser_navigate uses for web_search.
This commit is contained in:
@@ -408,12 +408,30 @@ def _rewrite_delegate_task(td: Dict[str, Any], available: set) -> Optional[Dict[
|
||||
return {**td, "function": {**fn, "description": desc}}
|
||||
|
||||
|
||||
_VAULT_INPUT_TOOL_HINT = "the browser's input tool"
|
||||
|
||||
|
||||
def _rewrite_browser_vault(td: Dict[str, Any], available: set) -> Optional[Dict[str, Any]]:
|
||||
"""Name the concrete input tool for typing the login identifier: `fill_input` inside browser_exec code, or
|
||||
browser_type on the built-in stack. Resolved here because the two live in different toolsets."""
|
||||
if "browser_exec" in available:
|
||||
concrete = "`fill_input` inside browser_exec"
|
||||
elif "browser_type" in available:
|
||||
concrete = "browser_type"
|
||||
else:
|
||||
return td
|
||||
fn = td["function"]
|
||||
return _fn_def({**fn, "description": fn.get("description", "").replace(_VAULT_INPUT_TOOL_HINT, concrete)})
|
||||
|
||||
|
||||
_DYNAMIC_SCHEMA_REWRITERS = {
|
||||
"execute_code": _rewrite_execute_code,
|
||||
"discord": _discord_rewriter("get_dynamic_schema_core"),
|
||||
"discord_admin": _discord_rewriter("get_dynamic_schema_admin"),
|
||||
"browser_navigate": _rewrite_browser_navigate,
|
||||
"browser_exec": _rewrite_browser_exec,
|
||||
"browser_vault_list": _rewrite_browser_vault,
|
||||
"browser_vault_fill": _rewrite_browser_vault,
|
||||
"delegate_task": _rewrite_delegate_task,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user