Noop detection by machine tag, not by matching the Chinese sentence

This commit is contained in:
AnyBot Dev 2026-11-09 17:10:25 +08:00
parent c67b07586d
commit ccfeaff235
3 changed files with 15 additions and 3 deletions

View File

@ -1152,7 +1152,7 @@ pub fn spawn(job: Job, bot_id: u64, tx: Sender<(u64, StreamEvent)>, cancel: Arc<
// any picture, shown and kept. // any picture, shown and kept.
let finish = |history: &mut Vec<Message>, output: &str, status: ToolStatus, image: Option<String>| { let finish = |history: &mut Vec<Message>, output: &str, status: ToolStatus, image: Option<String>| {
// A click that changed nothing on the screen is trouble too, though it "worked". // A click that changed nothing on the screen is trouble too, though it "worked".
if matches!(status, ToolStatus::Failed | ToolStatus::Denied) || !repeat_note.is_empty() || output.contains("畫面和上一步完全一樣") { if matches!(status, ToolStatus::Failed | ToolStatus::Denied) || !repeat_note.is_empty() || output.contains(crate::computer::NOOP_TAG) {
trouble.set(true); trouble.set(true);
} }
job.note(crate::oplog::Record::ToolFinished { op: job.op.clone(), call_id: call.id.clone(), status: format!("{status:?}").to_lowercase() }); job.note(crate::oplog::Record::ToolFinished { op: job.op.clone(), call_id: call.id.clone(), status: format!("{status:?}").to_lowercase() });

View File

@ -2085,7 +2085,7 @@ fn box_look(script: Option<&str>, after: Option<String>, pointer: bool) -> Resul
same same
}; };
if unchanged { if unchanged {
text.push_str("\n⚠️ 畫面和上一步完全一樣:這一步沒有點到東西。不要再做同一步;換一個編號、換一個方法(網頁用 browser_* 工具,或直接開網址),或用 hand_over_computer 請使用者幫忙。"); text.push_str(crate::computer::NOOP_NOTE);
} }
if lines.is_empty() { if lines.is_empty() {
text.push_str("\n畫面上沒有可以照編號點的東西:只好照圖上的位置點 x、y。"); text.push_str("\n畫面上沒有可以照編號點的東西:只好照圖上的位置點 x、y。");

View File

@ -220,6 +220,12 @@ pub fn is_pointer_step(name: &str) -> bool {
matches!(name, "computer_use_click" | "computer_use_scroll" | "computer_use_drag") matches!(name, "computer_use_click" | "computer_use_scroll" | "computer_use_drag")
} }
/// The screen-did-not-change note. The sentence is for the model; the tag at the end is for
/// the harness (agent.rs): control flow matches the TAG, never the words (a wording change
/// used to silently turn off the whole "same click did nothing" guard).
pub const NOOP_TAG: &str = "[[noop]]";
pub const NOOP_NOTE: &str = "\n⚠️ 畫面和上一步完全一樣:這一步沒有點到東西。不要再做同一步;換一個編號、換一個方法(網頁用 browser_* 工具,或直接開網址),或用 hand_over_computer 請使用者幫忙。[[noop]]";
/// What the bot is told after computer_use_show (the picture itself goes into the chat). /// What the bot is told after computer_use_show (the picture itself goes into the chat).
pub const SHOWN_NOTE: &str = "已把這台電腦現在的畫面(使用者看到的樣子,沒有編號)放進聊天,使用者看得到這張圖;你也看得到,可以用一兩句話說明畫面上有什麼"; pub const SHOWN_NOTE: &str = "已把這台電腦現在的畫面(使用者看到的樣子,沒有編號)放進聊天,使用者看得到這張圖;你也看得到,可以用一兩句話說明畫面上有什麼";
@ -1147,7 +1153,7 @@ fn look(after: Option<String>, pointer: bool) -> Result<(String, Option<String>)
same same
}; };
if unchanged { if unchanged {
text.push_str("\n⚠️ 畫面和上一步完全一樣:這一步沒有點到東西。不要再做同一步;換一個編號、換一個方法(網頁用 browser_* 工具,或直接開網址),或用 hand_over_computer 請使用者幫忙。"); text.push_str(crate::computer::NOOP_NOTE);
} }
if hidden > 0 { if hidden > 0 {
text.push_str(&format!("\n(「{app}」有 {hidden} 個按鈕被別的視窗擋住或不在這個桌面,沒有編號:先 computer_use_open_app 把它叫到前面。)")); text.push_str(&format!("\n(「{app}」有 {hidden} 個按鈕被別的視窗擋住或不在這個桌面,沒有編號:先 computer_use_open_app 把它叫到前面。)"));
@ -1772,6 +1778,12 @@ mod mac {
mod tests { mod tests {
use super::*; use super::*;
#[test]
fn the_noop_note_carries_its_tag() {
// The harness matches NOOP_TAG; the sentence may be reworded, the tag may not drift.
assert!(NOOP_NOTE.contains(NOOP_TAG));
}
/// Keys wait when the app in front isn't the one of the latest look (no real key is pressed /// Keys wait when the app in front isn't the one of the latest look (no real key is pressed
/// here: the check refuses before anything is sent, or there is no front app at all). /// here: the check refuses before anything is sent, or there is no front app at all).
#[test] #[test]