app
Fusion - the Fusion 360 Bridge
Public Made by Adomby adom
Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.
← Commit history
Publish 1.9.100
4 files changed
+40−20
bin/fusion-dashboard⋯ 1 unchanged line ⋯
dashboard/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "fusion-dashboard"-version = "1.9.98"+version = "1.9.100" dependencies = [ "serde_json", ]
dashboard/src/main.rs+32−9@@ -299,7 +299,7 @@ struct App { // Last GOOD status per target. While the bridge is busy (a tour, a long verb), readiness // calls time out and every field reads false - which used to paint the whole board RED // while the tour was visibly running (ralph, 2026-08-18). Unknowable is not broken.- last_good: Mutex<std::collections::HashMap<String, serde_json::Value>>,+ last_good: Mutex<std::collections::HashMap<String, (Instant, serde_json::Value)>>, // Boxes we are actively launching Fusion on, so the LED can say "opening right now" // instead of leaving the user guessing (John, 2026-08-18). launching: Mutex<std::collections::HashMap<String, Instant>>,@@ -1010,15 +1010,38 @@ fn handle_conn(app: &Arc<App>, mut stream: TcpStream) { } } if st["answered"].as_bool() == Some(true) {- app.last_good.lock().unwrap().insert(t.clone(), st.clone());- } else if let Some(prev) = app.last_good.lock().unwrap().get(&t).cloned() {- // Keep showing the last VERIFIED state and say it is stale, instead of flipping- // every LED red just because the bridge was too busy to answer.+ app.last_good.lock().unwrap().insert(t.clone(), (Instant::now(), st.clone()));+ } else if let Some((at, prev)) = app.last_good.lock().unwrap().get(&t).cloned() {+ // Keep showing the last VERIFIED state rather than flipping every LED red+ // because one probe was busy - BUT ONLY WHILE IT IS STILL PLAUSIBLY TRUE.+ //+ // ⚠️ A SNAPSHOT IS NOT A FACT (John, live 2026-08-20: "why is your fusion+ // dashboard not showing all green led's right now?"). AdomLapper's last_good+ // was captured while Fusion was DOWN. Every later probe lost a race inside+ // the six-verb fan-out, so this branch kept re-serving that dead snapshot -+ // and broadcasting it over SSE, overwriting good renders - for FIVE HOURS,+ // while fusion_readiness answered running:true ready:true on demand. The+ // dashboard confidently showed red for a box that was green.+ //+ // So the fallback is now TIME-BOUNDED and its age is always visible. Past the+ // window, "I cannot check right now" is reported honestly instead of dressing+ // up an old picture as the current one.+ let age = at.elapsed().as_secs(); let reason = st["busyReason"].clone();- st = prev;- st["stale"] = serde_json::Value::Bool(true);- st["busyReason"] = reason;- st["_hint"] = serde_json::json!("Showing the LAST VERIFIED state: the bridge is busy (a tour or long verb is running) so a fresh probe did not answer. Nothing here is broken - it is simply not re-checkable this second.");+ if age <= 180 {+ st = prev;+ st["stale"] = serde_json::Value::Bool(true);+ st["busyReason"] = reason;+ st["lastVerifiedAgeSec"] = serde_json::json!(age);+ st["_hint"] = serde_json::json!(format!(+ "Showing the state verified {}s ago: a fresh probe did not answer (the bridge is busy with a long verb). Nothing here is broken - it is simply not re-checkable this second.", age));+ } else {+ st["stale"] = serde_json::Value::Bool(true);+ st["lastVerifiedAgeSec"] = serde_json::json!(age);+ st["busyReason"] = reason;+ st["_hint"] = serde_json::json!(format!(+ "The bridge has not answered a status probe for {}s, and the last verified state is too old to keep presenting as current. Press refresh, or read fusion_readiness directly - it often answers alone even when the six-verb status fan-out does not.", age));+ } } app.hub.broadcast("state", &st); respond_json(&mut stream, &st);
page.json+7−10@@ -4,17 +4,13 @@ "type": "app", "description": "This package installs the bridge's SKILLS into your container so your AI knows how to drive it; Adom Bridge loads the bridge runtime itself from the release zip.", "dependencies": {- "adom/adom-desktop": "^1.9.0"+ "adom/adom-desktop": "*" }, "scripts": { "install": "./install.sh", "uninstall": "./uninstall.sh" }, "tags": [- "ab",- "bridge",- "fusion",- "desktop-app", "fusion360", "autodesk", "cad",@@ -74,10 +70,7 @@ "build a basic parts library", "add a 3d model to a component", "make a fusion 360 library with 3d",- "set up the fusion bridge",- "fusion dashboard",- "fusion status page",- "open the fusion launch page"+ "set up the fusion bridge" ], "discovery_pitch": "Use the Adom Bridge Fusion 360 bridge when the user wants to DRIVE Autodesk Fusion 360 from the cloud: open/search their team's Fusion cloud designs, lay out a PCB or do electronics, export STEP/IGES/STL/Gerbers/BOM, or build a component library with real rendering 3D. It runs Fusion on the user's own machine via Adom Bridge. NOT for web/browser/login/form-filling (that's the native-browser extension) and NOT for KiCad (that's the kicad bridge).", "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Bridge: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",@@ -106,5 +99,9 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ]+ ],+ "author": {+ "name": "John Lauer",+ "email": "[email protected]"+ } }