Hands: screen tools for the account's other computers; one pop-up per step; clearer TLS errors
- The brain's bots get computer_use_* for 手腳 (devices), as the prompt already said; before, they only had shell there and fell back to scrot, which can't see a Wayland desktop - After saying yes in the 「使用電腦工具」 pop-up (it shows the step), that same step isn't asked again (sending messages still asks every time) - A certificate failure says so instead of 「網路連線出了問題」 - install.sh restarts the background AnyBot after an update Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Uirha3oEtWeHh58zA7ErHa
This commit is contained in:
parent
2bc573f095
commit
c71e8357b8
|
|
@ -292,6 +292,10 @@ case $MODE in
|
|||
sh "$SRC/deploy/linux/install.sh" >/dev/null || die "安裝失敗。" "執行 sh $SRC/deploy/linux/install.sh 看錯誤。"
|
||||
ok "程式放在 ~/.local/bin/anybot"
|
||||
[ "$MODE" = app ] && ok "應用程式選單裡有 AnyBot"
|
||||
# 更新: the one running in the background (anybot setup's service) switches to the new one.
|
||||
if systemctl --user is-active --quiet anybot 2>/dev/null; then
|
||||
systemctl --user restart anybot && ok "重新啟動背景執行的 AnyBot(換成新版)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
PATH="$HOME/.local/bin:$PATH"
|
||||
|
|
|
|||
19
src/agent.rs
19
src/agent.rs
|
|
@ -630,6 +630,9 @@ pub fn spawn(job: Job, bot_id: u64, tx: Sender<(u64, StreamEvent)>, cancel: Arc<
|
|||
// Permission to use computers at all, and this Mac in particular, is asked for
|
||||
// when it's needed instead of the step failing quietly.
|
||||
let mut gate: Result<(), String> = Ok(());
|
||||
// The person just said yes to this very step in a switch's pop-up (it shows the
|
||||
// step): no second pop-up for it.
|
||||
let mut said_yes = false;
|
||||
// 直接操作: like Grok Bot after its one-time setup ("讓 Grok Bot 在你的電腦上開啟檔案和
|
||||
// 執行任務。自動審核仍會先檢查所有操作", ENHi8c), nothing is asked except what the
|
||||
// safety checks and the person's "一律詢問" rules stop.
|
||||
|
|
@ -642,8 +645,11 @@ pub fn spawn(job: Job, bot_id: u64, tx: Sender<(u64, StreamEvent)>, cancel: Arc<
|
|||
if !tools_on {
|
||||
let reason = format!("讓 {} 使用電腦工具:{}\n(在 {} 上)", job.via_name, what, t.name);
|
||||
match ask_person(ApprovalKind::EnableTools, reason, "tools:on".into()) {
|
||||
ApprovalAnswer::Once => {}
|
||||
ApprovalAnswer::Always(_) => tools_on = true,
|
||||
ApprovalAnswer::Once => said_yes = true,
|
||||
ApprovalAnswer::Always(_) => {
|
||||
tools_on = true;
|
||||
said_yes = true;
|
||||
}
|
||||
ApprovalAnswer::Reject => gate = Err("使用者沒有允許使用電腦工具。請改用文字回答,或問使用者想怎麼做。".into()),
|
||||
}
|
||||
}
|
||||
|
|
@ -654,8 +660,11 @@ pub fn spawn(job: Job, bot_id: u64, tx: Sender<(u64, StreamEvent)>, cancel: Arc<
|
|||
if gate.is_ok() && matches!(t.place, tools::Place::Local { .. }) && !local_on {
|
||||
let reason = format!("在你的電腦上執行任務,而不只是在它自己的電腦上:{}{what}\n(在 {} 上)", if is_web { format!("{} ", web::label(&call.name)) } else { String::new() }, t.name);
|
||||
match ask_person(ApprovalKind::EnableThisComputer, reason, "local:on".into()) {
|
||||
ApprovalAnswer::Once => {}
|
||||
ApprovalAnswer::Always(_) => local_on = true,
|
||||
ApprovalAnswer::Once => said_yes = true,
|
||||
ApprovalAnswer::Always(_) => {
|
||||
local_on = true;
|
||||
said_yes = true;
|
||||
}
|
||||
ApprovalAnswer::Reject => gate = Err(format!("使用者沒有允許在「{}」上執行。可以改用「{}」,或問使用者。", t.name, crate::model::BOT_COMPUTER_NAME)),
|
||||
}
|
||||
}
|
||||
|
|
@ -764,6 +773,8 @@ pub fn spawn(job: Job, bot_id: u64, tx: Sender<(u64, StreamEvent)>, cancel: Arc<
|
|||
let approved = match decision {
|
||||
_ if gate.is_err() => Err((gate.clone().unwrap_err(), ToolStatus::Denied)),
|
||||
Decision::Allow => Ok(()),
|
||||
// Sending (Messages, mail…) still asks every time, even right after a switch.
|
||||
Decision::Ask { .. } if said_yes && !(is_mac && crate::macapps::is_send(&call.name)) => Ok(()),
|
||||
Decision::Deny(r) => Err((format!("被安全規則擋下:{r}"), ToolStatus::Denied)),
|
||||
Decision::Ask { reason, grant } => {
|
||||
let machine = target.as_ref().map(|t| t.name.clone()).unwrap_or_default();
|
||||
|
|
|
|||
|
|
@ -698,6 +698,8 @@ impl App {
|
|||
if crate::computer::screen_supported() {
|
||||
screens.push(crate::model::THIS_COMPUTER_NAME.to_string());
|
||||
}
|
||||
// …and the account's other computers (手腳): their own AnyBot looks and clicks there.
|
||||
screens.extend(devices.iter().cloned());
|
||||
if cfg!(target_os = "macos") {
|
||||
tool_specs.extend(crate::macapps::specs().into_iter().filter(|t| self.state.messages_send || t["name"] != crate::macapps::SEND_MESSAGE));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -720,6 +720,10 @@ pub fn why_unreachable(e: &ureq::Error) -> String {
|
|||
use std::io::ErrorKind as K;
|
||||
use ureq::Error as E;
|
||||
let text = e.to_string().to_lowercase();
|
||||
// A TLS failure often comes wrapped as an I/O error: look at the words first.
|
||||
if text.contains("certificate") || text.contains("tls") || text.contains("handshake") {
|
||||
return "和伺服器的安全連線失敗:對方的憑證不對(網址可能連到了別的服務,或憑證過期)".to_string();
|
||||
}
|
||||
let w = match e {
|
||||
E::HostNotFound => "找不到伺服器:這台電腦可能沒連上網路,或伺服器網址打錯了",
|
||||
E::ConnectionFailed => "伺服器沒有回應:可能沒開機,或網路把連線擋住了",
|
||||
|
|
@ -731,7 +735,6 @@ pub fn why_unreachable(e: &ureq::Error) -> String {
|
|||
K::NetworkUnreachable | K::HostUnreachable | K::NetworkDown | K::AddrNotAvailable => "這台電腦沒有連上網路",
|
||||
_ => "網路連線出了問題",
|
||||
},
|
||||
_ if text.contains("tls") || text.contains("certificate") => "和伺服器的安全連線失敗(伺服器的憑證有問題)",
|
||||
_ if text.contains("dns") || text.contains("resolve") => "找不到伺服器:這台電腦可能沒連上網路,或伺服器網址打錯了",
|
||||
_ => "網路連線出了問題",
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue