An upload says what the field holds now and what the page showed

The tool only said it put the file in; on a page that shows nothing about it the bot spent five
more steps checking (shell, read, screenshot, two scripts). Now the result names the file the
field holds (and its size) and the page's new text, and an empty field is an error. Real run in
the gVisor box with Grok: the sign-up form went from 10 steps / 35 s to 6 / 20 s; the second
time it followed the skill it had learned, by names only, 6 steps / 21 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uirha2RVfSYmrhqNnqx9Z4
This commit is contained in:
王性驊 2026-11-07 00:28:35 +08:00
parent 9a23411e51
commit 19f8257e48
2 changed files with 12 additions and 2 deletions

View File

@ -1625,7 +1625,7 @@ printf 'a,b\n1,2\n' > report.csv && printf 'hello box' > '/tmp/anybot-up/上傳
}
assert!(results[0].contains("served"), "{}", results[0]);
assert!(results[1].contains("檔案測試"), "{}", results[1]);
assert!(results[2].contains("已把 /tmp/anybot-up/上傳測試.txt 放進上傳欄位"), "{}", results[2]);
assert!(results[2].contains("已把 /tmp/anybot-up/上傳測試.txt 放進上傳欄位,欄位裡現在是:上傳測試.txt(9 位元組)") && results[2].contains("已選:上傳測試.txt 9"), "{}", results[2]);
assert!(results[3].contains("已選:上傳測試.txt 9"), "{}", results[3]);
assert!(results[4].contains("這台電腦上沒有「/tmp/anybot-up/沒有這個.txt」"), "{}", results[4]);
assert!(results[5].contains("下載好了:/home/bot/Downloads/report.csv"), "{}", results[5]);

View File

@ -727,10 +727,20 @@ pub fn run(name: &str, args: &Value) -> Result<(String, Option<String>), String>
let js = format!("(() => {{ let el = {}; if (el && el.tagName !== 'INPUT') el = el.querySelector('input[type=file]') || el.closest('label')?.querySelector('input[type=file]'); return el || document.querySelector('input[type=file]'); }})()", find_js(&rf, &text));
let r = tab.call("Runtime.evaluate", json!({"expression": js, "returnByValue": false}))?;
let obj = r["result"]["objectId"].as_str().ok_or("這一頁找不到上傳檔案的欄位")?.to_string();
let before = snapshot(&mut tab);
tab.call("DOM.setFileInputFiles", json!({"files": [full], "objectId": obj}))?;
tab.eval(&format!("(() => {{ const el = {js}; if (el) el.dispatchEvent(new Event('change', {{bubbles: true}})); return 1; }})()"))?;
settle(1000);
Ok((format!("已把 {full} 放進上傳欄位。"), None))
// What the field holds now (a page that shows nothing about it left the bot
// checking with five more steps), and what the page did with it.
let held = tab.eval(&format!("(() => {{ const el = {js}; return el && el.files ? Array.from(el.files).map(f => f.name + '(' + f.size + ' 位元組)').join('、') : ''; }})()")).ok().and_then(|v| v.as_str().map(String::from)).unwrap_or_default();
if held.is_empty() {
return Err(format!("放了 {full},但上傳欄位還是空的(這一頁可能要先按「上傳」之類的按鈕,或欄位不是這一個)。"));
}
let after = snapshot(&mut tab);
let seen = changes(&before, &after);
let seen = if seen.contains("沒有變化") { String::new() } else { format!("\n{seen}") };
Ok((format!("已把 {full} 放進上傳欄位,欄位裡現在是:{held}。{seen}"), None))
}
"browser_download" => {
// The file lands on the browser's own disk: Bot 的電腦's when it runs there.