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
Update 15 file(s)
11 files changed
+45−23
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.9.191+1.9.192
adom-bridge-fusion-manifest.json+4−4@@ -1,10 +1,10 @@ { "manifest_version": 1, "name": "fusion360",- "version": "1.9.191",- "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.191/adom-bridge-fusion-v1.9.191.zip",- "sha256": "179b2c54314dffd2351ed8b233a87f20d30bb1151f1ee3039f4fc78851887f68",- "size": 494167,+ "version": "1.9.192",+ "url": "https://wiki.adom.inc/download/adom/fusion-bridge/1.9.192/adom-bridge-fusion-v1.9.192.zip",+ "sha256": "4c57175e91b1b4b03a782747b51a8aa2e71023a0ca4c689094041f3645b8b48e",+ "size": 494207, "verbPrefixes": [ "fusion_" ],
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.9.191",+ "version": "1.9.192", "description": "Drive Autodesk Fusion 360 from the cloud: launch Fusion, electronics board layout, design rules, exports (STEP/IGES/STL/3MF/USDZ/OBJ/DXF/DWG/Gerbers/BOM/CPL), fast APS server-indexed cloud search plus browse/recent/file-info/versions, cloud file download/upload and folder creation, and in-app parametric modeling (fusion_run_modeling_script). Never-charge: APS calls are capped to the free tier.", "homepage": "https://wiki.adom.inc/adom/fusion-bridge", "author": "Adom Inc.",
dashboard/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "fusion-dashboard"-version = "1.9.191"+version = "1.9.192" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.191"+version = "1.9.192" edition = "2021" [dependencies]
dashboard/src/main.rs+16−3@@ -274,7 +274,14 @@ fn action(ai_thread: &str, target: &str, name: &str, args: &serde_json::Value) - // view - transport buttons + the live caption, clickable while they watch // Fusion. Best-effort: no pup, no problem, the dashboard page has the same // controls. Opened FOREGROUND deliberately - the user just pressed Run.- if let Some(id) = unwrap_data(&r)["demoId"].as_str() {+ let dug = {+ let d = unwrap_data(&r);+ if d["demoId"].is_string() { d }+ else if let Some(o) = d["output"].as_str() {+ serde_json::from_str::<serde_json::Value>(o).unwrap_or(d)+ } else { d }+ };+ if let Some(id) = dug["demoId"].as_str() { let url = format!("{}?remote={}", url_for(current_port()), id); let args = serde_json::json!({"url": url, "sessionId": format!("fusion-tour-remote-{}", id), "width": 320, "height": 420, "left": 40, "top": 120,@@ -282,9 +289,15 @@ fn action(ai_thread: &str, target: &str, name: &str, args: &serde_json::Value) - "foregroundReason": "the user just started the Fusion tour; this is its stop/pause remote"}).to_string(); let ai2 = ai_thread.to_string(); let t2 = target.to_string(); std::thread::spawn(move || {- let _ = Command::new("adom-bridge")+ match Command::new("adom-bridge") .args(["--ai-thread", &ai2, "--target", &t2, "pup_open_window", &args])- .output();+ .output() {+ Ok(o) if o.status.success() =>+ eprintln!("[dash] tour remote floaty opened"),+ Ok(o) => eprintln!("[dash] tour remote floaty FAILED: {}",+ String::from_utf8_lossy(&o.stderr).chars().take(200).collect::<String>()),+ Err(e) => eprintln!("[dash] tour remote floaty spawn error: {}", e),+ } }); } r
dashboard/ui/index.html+7−2@@ -414,7 +414,9 @@ if(REMOTE_ID){ '<button class="btn" id="rExit" style="border-color:rgba(248,81,73,.5);color:var(--red)" data-tip="End the tour">⏹ Exit tour</button>'+ '</div></div>'; let rp=false;- const rctl=async(a)=>{try{await act('tour_control',{demoId:REMOTE_ID,action:a});+ const rctl=async(a)=>{try{+ let ok=await act('tour_control',{demoId:REMOTE_ID,action:a}).catch(()=>null);+ if(!ok)await act('tour_control',{demoId:REMOTE_ID,action:a}); if(a==='pause'){rp=true;$('#rPause').innerHTML='▶';} if(a==='resume'){rp=false;$('#rPause').innerHTML='⏸';} }catch(e){}};@@ -558,7 +560,10 @@ $('#btnTour').onclick=async()=>{ if(tourAudioOn()&&caps.length){(async()=>{for(const c of caps){try{await fetch('api/tts?text='+encodeURIComponent(c));}catch(e){}}})();} const tt=$('#tourTransport');tt.style.display='flex'; let ttPaused=false;- const ctl=async(action)=>{try{const r=await act('tour_control',{demoId:id,action});const x=r.data||r;+ const ctl=async(action)=>{try{+ let r=await act('tour_control',{demoId:id,action}).catch(()=>null);+ if(!r)r=await act('tour_control',{demoId:id,action}); // one silent retry - a slow relay hop must not eat a pause click+ const x=r.data||r; if(x.success===false){toast(x.error||'control refused','err');return;} if(action==='pause'){ttPaused=true;$('#ttPause').innerHTML='▶';toast('pausing at the next step boundary');} if(action==='resume'){ttPaused=false;$('#ttPause').innerHTML='⏸';toast('resuming');}
install.sh+1−1@@ -21,7 +21,7 @@ echo "Installed fusion-bridge skills: $(ls "$PKG_DIR/skills" 2>/dev/null | tr '\ # binary (the three-artifact pattern: bridge zip -> ab, THIS pkg -> container skills + # this download, page media -> wiki). Per the wiki's PKG_VS_RELEASE policy, binaries are # platform-tagged RELEASE assets, never tarball content - the installer fetches them.-DASH_VERSION="1.9.191"+DASH_VERSION="1.9.192" DASH_URL="https://wiki.adom.inc/download/adom/fusion-bridge/${DASH_VERSION}/fusion-dashboard" DEST="" if [ -w /usr/local/bin ]; then DEST=/usr/local/bin
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.9.191",+ "version": "1.9.192", "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": {
page.json+11−8@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.9.191",+ "version": "1.9.192", "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": {@@ -11,6 +11,10 @@ "uninstall": "./uninstall.sh" }, "tags": [+ "ab",+ "bridge",+ "fusion",+ "desktop-app", "fusion360", "autodesk", "cad",@@ -75,7 +79,10 @@ "build a basic parts library", "add a 3d model to a component", "make a fusion 360 library with 3d",- "set up the fusion bridge"+ "set up the fusion bridge",+ "fusion dashboard",+ "fusion status page",+ "open the fusion launch page" ], "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.",@@ -104,9 +111,5 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ],- "author": {- "name": "John Lauer",- "email": "[email protected]"- }-}+ ]+}
server.py+1@@ -8395,6 +8395,7 @@ def _orchestrate_demo_tour(args: dict) -> dict: "open-design: %r never became the active document within 170s" % query) state["designOpenFailed"] = True elif key == "datahub":+ _wait_idle() # ralph run 649s: the 3D save was still grinding; busy != broken r = _proxy_to_addin("list_cloud_projects", {}, timeout=45) if r.get("success"): _d = r.get("data") or {}