app
Altium - the Altium Bridge
Public Made by Adomby adom
Adom Bridge for Altium Designer: a resident DelphiScript agent gives the AI eval, the 1,100-command process launcher, all 8 EDA surfaces with screenshots, compile/ERC, DRC, OutJob outputs, native SchLib/PcbLib authoring with STEP 3D bodies, and dialog handling by PID.
← Commit history
0.2.23 source: altium_selftest_script_error (regression test for the script-error safety net)
7 files changed
+37−7
bridge-rs/Cargo.lock+1−1@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "altium-bridge"-version = "0.2.22"+version = "0.2.23" dependencies = [ "getrandom", "serde",
bridge-rs/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "altium-bridge"-version = "0.2.22"+version = "0.2.23" 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/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.22";+pub const BRIDGE_VERSION: &str = "0.2.23"; 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-rs/src/verbs.rs+19−1@@ -35,7 +35,7 @@ pub const KNOWN: &[&str] = &[ "clone_symbol", "rename_symbol", "rename_footprint", "remove_symbol", "remove_footprint", "copy_footprint", "xcopy_footprint", "swap_footprint", "symbol_mode", "cleanup_libs", "install_library", "install_library_bundle", "install_receipt", "compile_intlib", "extract_intlib",- "place_on_sch", "place_on_pcb", "import_part", "add_symbol_art", "symbol_prims", "set_models",+ "place_on_sch", "place_on_pcb", "import_part", "add_symbol_art", "symbol_prims", "set_models", "selftest_script_error", // licence / account "license", "license_status", "ensure_licensed", "setup_trial", "signin", "signin_status", "connect_workspace",@@ -110,6 +110,9 @@ fn describe() -> Value { verb_doc("plate_vias", "Make every drilled pad in a PcbLib a plated MULTI-LAYER pad (all footprints, or footprintName). adom-lbr writes heatsink vias as pads with a hole; Altium loaded them on the Top Layer, so a thermal pad's vias were not through-holes until this ran.", json!({"libraryPath": "path (.PcbLib)", "footprintName": "string (optional filter)"}), json!({"holes": "int", "plated": "int", "fixed": "Fp:Pad;..."}), 90, "altium_save the PcbLib afterwards; footprint_primitives on a placed part should then report layerId 74 for the vias.", &["normalize_bodies", "footprint_primitives", "save"], &["Read-modify in place: run once per library install."], json!({"libraryPath": "C:/lib/Adom_ToF.PcbLib"})),+ verb_doc("selftest_script_error", "Regression test for the script-error safety net (from 0.2.23): makes the agent raise a REAL DelphiScript runtime error on purpose and checks that the bridge photographs Altium's Error box, stops the halted script itself and leaves no dialog behind. Flashes one error box for under a second. Run it after any change to agent.rs / dialogs.rs and once on every new Altium build.",+ json!({}), json!({"netWorks": "bool", "errorShot": "base64 png", "autoRecovered": "bool", "dialogsLeft": "int"}), 60,+ "netWorks:true is the pass. The agent is stopped afterwards by design; the next verb restarts it.", &["agent_recover", "dialog_log", "agent_status"], &["It really does halt the engine for a moment: do not run it while a user is mid-edit in Altium."], json!({})), verb_doc("symbol_prims", "Read a SchLib component's drawing: primitive counts by kind, body rectangle, polyline bounding box, display mode and the footprint models. Read-only, use it to verify add_symbol_art / set_models.", json!({"libraryPath": "path (.SchLib)", "symbolName": "string", "models": "bool, default false (the model walk halts the engine on some builds)"}), json!({"pins": "int", "rectangles": "int", "lines": "int", "polylines": "int", "bodyRectMil": "[..]", "polyBboxMil": "[..]", "models": "[\"PCBLIB:NAME\"]"}), 60, "polylines should equal what add_symbol_art reported and polyBboxMil should sit inside bodyRectMil.", &["add_symbol_art", "set_models", "read_symbol"], &[], json!({})),@@ -492,6 +495,21 @@ pub fn dispatch(command: &str, args: &Value, _forwarded: &[(String, String)]) -> "extract_intlib" => library::extract_intlib(args), "place_on_sch" => library::place_on_sch(args), "add_symbol_art" => library::add_symbol_art(args),+ "selftest_script_error" => {+ let mut r = agent::call("selftest_halt", &[], None, Duration::from_secs(45));+ let caught = r.get("errorCode").and_then(|c| c.as_str()) == Some("agent_script_error");+ let recovered = r.get("autoRecovered").and_then(|b| b.as_bool()).unwrap_or(false);+ let dialogs_left = crate::dialogs::scan().len();+ r["netWorks"] = json!(caught && recovered && dialogs_left == 0);+ r["dialogsLeft"] = json!(dialogs_left);+ r["success"] = json!(caught && recovered && dialogs_left == 0);+ r["_hint"] = json!(if caught && recovered && dialogs_left == 0 {+ "PASS: the deliberate runtime error was caught, photographed (errorShot), the halted script was stopped (EditScript:Stop) and nothing is left on the user's screen. The next verb restarts the agent."+ } else {+ "FAIL: the safety net did not fully handle a deliberate script error. altium_agent_recover, then fix agent.rs/dialogs.rs before shipping."+ });+ r+ } "symbol_prims" => library::symbol_prims(args), "set_models" => library::set_models(args), "place_on_pcb" => library::place_on_pcb(args),
bridge.json+3−2@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "altium", "displayName": "Altium Designer",- "version": "0.2.22",+ "version": "0.2.23", "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",@@ -92,12 +92,12 @@ "altium_list_nets", "altium_net_connections", "altium_normalize_bodies",- "altium_plate_vias", "altium_open_document", "altium_open_project", "altium_pcb_report", "altium_place_on_pcb", "altium_place_on_sch",+ "altium_plate_vias", "altium_progress", "altium_read_board", "altium_read_rules",@@ -117,6 +117,7 @@ "altium_run_script", "altium_save", "altium_schematic_data",+ "altium_selftest_script_error", "altium_set_layer_visibility", "altium_set_models", "altium_set_params",
page.json+1−1@@ -140,4 +140,4 @@ "skills/altium-wiki-import/SKILL.md", "uninstall.sh" ]-}+}
src/agent/AdomAgent.pas.tmpl+11@@ -1558,6 +1558,16 @@ End; { Read a SchLib component drawing: primitive counts by kind, the body rectangle, the polyline bounding box and the footprint models. Args: libref }+{ Regression test for the script-error safety net: raise a REAL runtime error inside the agent's+ own code, on purpose. The bridge must photograph the Error box, stop the halted script itself+ and answer agent_script_error; a timeout here means the net is broken. Never call this except+ through altium_selftest_script_error. }+Function CmdSelfTestHalt(Lines : TStringList) : String;+Begin+ AdomDeliberateUndeclaredIdentifierForSelfTest(1);+ Result := '{' + JRaw('ok', 'false') + ',' + JStr('error', 'the engine did not halt: this Altium build tolerated an undeclared identifier') + '}';+End;+ Function CmdSymbolPrims(Lines : TStringList) : String; Var SLib : ISch_Lib;@@ -4532,6 +4542,7 @@ Begin Else If Cmd = 'add_body' Then Result := CmdAddBody(Lines) Else If Cmd = 'place_on_sch' Then Result := CmdPlaceOnSch(Lines) Else If Cmd = 'add_symbol_art' Then Result := CmdAddSymbolArt(Lines, Payload)+ Else If Cmd = 'selftest_halt' Then Result := CmdSelfTestHalt(Lines) Else If Cmd = 'symbol_prims' Then Result := CmdSymbolPrims(Lines) Else If Cmd = 'set_models' Then Result := CmdSetModels(Lines) Else If Cmd = 'place_on_pcb' Then Result := CmdPlaceOnPcb(Lines)