← Commit history

0.2.22 source: script-error net covers the Continue-execution X2 box

John Lauer ·da394774a3 ·1mo ago ·parent 1648a23
7 files changed +35−6
bridge-rs/Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "altium-bridge"-version = "0.2.21"+version = "0.2.22" dependencies = [  "getrandom",  "serde",
bridge-rs/Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "altium-bridge"-version = "0.2.21"+version = "0.2.22" edition = "2021" description = "Adom altium-bridge — the bridge process, in Rust. Calls ab's verbs for the desktop; speaks file IPC to the resident DelphiScript agent inside Altium." license = "MIT"
bridge-rs/src/agent.rs+24
@@ -196,6 +196,30 @@ pub fn call_in(ws: &std::path::Path, command: &str, params: &[(&str, String)], p         // not leave Altium parked in its debugger: stop the script now and say what happened.         if t0.elapsed() >= next_halt_check {             next_halt_check = t0.elapsed() + Duration::from_millis(400);+            // Variant 2 (script run from INSIDE the agent, e.g. eval): Altium asks "Undeclared+            // identifier ... Continue execution?" in an 'X2' box with OK + Cancel. It is OURS (it+            // only exists while our command runs), the reaper rightly never touches a two-button+            // box, and the agent loop is blocked behind it. OK = continue: the loop survives.+            for d in crate::dialogs::scan() {+                let title = d.get("title").and_then(|t| t.as_str()).unwrap_or("").trim().to_string();+                let labels: Vec<String> = d.get("buttons").and_then(|b| b.as_array())+                    .map(|a| a.iter().filter_map(|x| x.as_str()).map(|s| s.trim().to_lowercase()).collect()).unwrap_or_default();+                let hwnd = d.get("hwnd").and_then(|h| h.as_i64());+                if title != "X2" || labels != ["ok", "cancel"] || hwnd.is_none() { continue; }+                let hwnd = hwnd.unwrap();+                let shot = crate::ab::call("desktop_screenshot_base64", json!({"hwnd": hwnd}), &[], 10);+                let img = shot.get("image").or_else(|| shot.get("base64")).cloned().unwrap_or(Value::Null);+                let pressed = crate::dialogs::press(hwnd, "OK").get("success").and_then(|b| b.as_bool()).unwrap_or(false);+                crate::dialogs::note_event(json!({"title": "X2", "category": "script_error_continue", "pressed": "OK", "ok": pressed,+                    "note": format!("script runtime error inside agent command '{command}': photographed, answered OK (continue) so the agent loop survives")}));+                let settle = Instant::now();+                while settle.elapsed() < Duration::from_secs(3) && !resp.exists() { std::thread::sleep(Duration::from_millis(20)); }+                let _ = std::fs::remove_file(&resp);+                return json!({"success": false, "errorCode": "agent_script_error", "command": command,+                    "error": format!("the script run by '{command}' raised a runtime error (Altium asked 'Continue execution?'; its text is in errorShot)"),+                    "errorShot": img, "answered": "OK", "answeredOk": pressed, "agentAlive": is_alive(),+                    "_hint": "READ errorShot (PNG of Altium's box, e.g. 'Undeclared identifier: X at Line:N'). The bridge answered OK so the agent loop is still resident; fix the script text and send it again."});+            }             if let Some(ev) = crate::dialogs::script_error_since(posted_unix_ms) {                 let recovered = crate::lifecycle::recover(&format!("auto: script Error box during agent command '{command}'"));                 return json!({"success": false, "errorCode": "agent_script_error", "command": command,
bridge-rs/src/main.rs+1−1
@@ -25,7 +25,7 @@ mod win32; use std::time::Instant; use tiny_http::{Header, Method, Response, Server}; -pub const BRIDGE_VERSION: &str = "0.2.21";+pub const BRIDGE_VERSION: &str = "0.2.22";  fn json_response(status: u16, body: &serde_json::Value) -> Response<std::io::Cursor<Vec<u8>>> {     let data = serde_json::to_vec(body).unwrap_or_else(|_| b"{}".to_vec());
bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "altium",   "displayName": "Altium Designer",-  "version": "0.2.21",+  "version": "0.2.22",   "description": "Drive Altium Designer from Adom: a resident DelphiScript agent (eval + the 1,100-command process launcher), the X2 -R command line, UIA over the VCL shell, dialogs by PID, screenshots of every Altium window, and Altium 365.",   "homepage": "https://wiki.adom.inc/adom/altium-bridge",   "docs": "https://wiki.adom.inc/adom/altium-bridge",
dev-skills/altium-bridge-dev/SKILL.md+6−1
@@ -85,7 +85,12 @@ when a script is stopped on a breakpoint"). Also: `ISch_Component.Implementation `.Implementation[i]` do not exist on AD 26.9.1 (walk models with a `SchIterator_Create` + `AddFilter_ObjectSet(MkSet(eImplementation))`). Every identifier in this section that a regex can recognise is in `scripts/release.py` `ENGINE_HALTING`, and a build that contains one is refused:-add to that list whenever you find another. Test new agent commands on a SECOND Altium build+add to that list whenever you find another. From 0.2.22 the same net covers the second shape: a script run from INSIDE the agent (`eval`) raises an+`X2` box "Undeclared identifier ... Continue execution?" with OK + Cancel; `agent::call` photographs it,+answers OK (the loop survives) and returns the same `agent_script_error`. To prove the net after any change+to `agent.rs`/`dialogs.rs`: `altium_eval {text:"Begin NoSuchProcAdomTest(1); End;"}` must come back in+seconds with `errorShot`, and `altium_status` must then read `ready: true` with no dialogs.+Test new agent commands on a SECOND Altium build before promoting; one machine proved nothing about 26.9.1.  ## The brace rule for JSON-building code
page.json+1−1
@@ -140,4 +140,4 @@     "skills/altium-wiki-import/SKILL.md",     "uninstall.sh"   ]-}\ No newline at end of file+}