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
add fusion_demo: one-verb first-time-user tour (finishes Autodesk sign-in via native browser, sets up APS + live sample search, walks project -> schematic -> 2D board -> 3D board with screenshots). Docs, hints, skill, README section
7 files changed
+310−7
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.6.77+1.6.84
README.md+31@@ -10,6 +10,37 @@ calling AI never has to guess. "generate an IPC SOIC-8 with LM358 etched on top and export the STEP" - just ask Claude ``` +## The demo: one verb, a whole guided tour (`fusion_demo`)++New to this? Run **one verb** and watch:++```bash+adom-desktop fusion_demo '{}'+```++`fusion_demo` takes a first-time user from nothing to a real board. It launches Fusion, **finishes+the Autodesk sign-in**, turns on cloud search, and then walks the actual story of a PCB:++**electronics project -> schematic -> 2D board layout -> 3D board**, screenshotting each view.++It is **staged and resumable**: each call advances as far as it safely can and returns `stage`,+`done`, a `narrate` line written for a newcomer, the `screenshots` to show them, and a `_hint` with+the exact next action. Keep calling it until `done:true`.++Two things it deliberately does NOT do:++- **It never leaves you parked on the sign-in page.** It drives the sign-in through your **native+ browser** (via the Adom browser extension), because that profile is usually already signed into+ Autodesk - one click instead of a password + 2FA. An anonymous automation browser would force a+ full fresh login, so the demo never uses one.+- **It never just name-drops cloud search.** It sets **APS** up for you, then runs a live sample+ search so you watch your whole Autodesk hub return results in about two seconds.++If you decline the cloud-search setup, run `fusion_demo '{"stage":"skip_aps"}'` and the tour+continues without it. To demo a specific design: `fusion_demo '{"query":"BQ25792"}'`.++Playbook for the AI running it: the bundled **fusion-demo** skill.+ ## Component library manager - the Adom basic parts library The bridge builds and opens full EAGLE-format component libraries in Fusion's library editor. Below:
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.6.77",+ "version": "1.6.84", "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/adom-desktop-fusion-bridge", "author": "Adom Inc.",
describe.py+5@@ -37,6 +37,11 @@ _T = [ {"success": "bool", "targets": "list"}, 20, None, False, {"title": "Fusion needs you", "body": "Please complete the Autodesk 2FA prompt on winvm - everything else is done."}), + ("fusion_demo", "FIRST-TIME-USER DEMO in one verb - the thing to run when someone new wants to SEE what this bridge does (HD's installer calls this). Takes them from nothing to a real board: launches Fusion, FINISHES the Autodesk sign-in (driven in the user's NATIVE browser via ABE/nbrowser_*, which is already signed into Autodesk - never pup, which is anonymous), sets up APS cloud search (or explains it if declined) and runs a LIVE sample search so they see 2-second results, then opens an electronics PROJECT and walks SCHEMATIC -> 2D BOARD -> 3D BOARD, screenshotting each view to show them. STAGED + RESUMABLE: every call advances as far as it safely can and returns stage/done/narrate/screenshots plus a _hint with the exact next action; keep calling it until done:true. NEVER leave a first-time user parked on the sign-in screen - that is the failure this verb exists to prevent. See the 'fusion-demo' skill.",+ {"query": "optional str (design to demo; else picked from APS search)", "stage": "optional str ('skip_aps' to proceed without cloud search)"},+ {"stage": "str", "done": "bool", "narrate": "str", "screenshots": "[{label,path}]", "steps": "[str]", "apsSampleSearch": "[{name,project}]"},+ 240, "fusion_demo", True, {}),+ # ── Cloud search & files (APS) ───────────────────────────────────────── ("fusion_aps_status", "APS state: configured, signed in, token live, never-charge meter.", {}, {"configured": "bool", "signedIn": "bool", "neverCharge": "bool"}, 20, None, False, {}),
page.json+4−4@@ -1,6 +1,6 @@ { "slug": "adom-desktop-fusion-bridge",- "version": "1.6.83",+ "version": "1.6.84", "type": "app", "description": "Installs this bridge's skills into your container so your AI knows how to drive the bridge. The bridge runtime itself is loaded by Adom Desktop from the release zip.", "dependencies": {@@ -51,7 +51,8 @@ "skills/fusion-multipart-libraries/**", "skills/fusion-onboarding/**", "skills/fusion-molecule-export/**",- "skills/pcb-stackup/**"+ "skills/pcb-stackup/**",+ "skills/fusion-demo/**" ], "discovery_triggers": [ "drive fusion 360",@@ -72,6 +73,5 @@ "set up the fusion bridge" ], "discovery_pitch": "Use the Adom Desktop 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 Desktop. 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 Desktop: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling.",- "visibility": "public"+ "brief": "Drive Autodesk Fusion 360 from the cloud via Adom Desktop: component libraries, IPC package generation, board layout, exports (STEP/Gerbers/BOM/CPL), fast APS cloud search, and parametric modeling." }
server.py+174−1@@ -1348,7 +1348,9 @@ def _handle_fusion_readiness(fusion_info: dict, args: dict) -> dict: "sign-in code EXPIRES in ~2 min; on a high-latency VM slow screenshot/click round-trips " "let it expire ('Sign-in request expired') and you loop. Minimize steps; if it expires, " "click Fusion 'Sign In' again for a FRESH code (the browser session stays warm). "- "Then poll until ready:true.")+ "Then poll until ready:true. FIRST-TIME DEMO? Run fusion_demo instead - it drives this "+ "sign-in through the user's NATIVE browser (already signed into Autodesk) and then "+ "gives them a real guided tour (project -> schematic -> 2D board -> 3D board).") elif ready and stale_info.get("addinStale"): hint = stale_info["_staleHint"] elif ready:@@ -3576,6 +3578,175 @@ def _orchestrate_fetch_optimized_glb(args: dict) -> dict: "message": "Job %s still %s; re-call fusion_fetch_optimized_glb to finish." % (job_id, res.get("status") or "processing")} +def _orchestrate_demo(args: dict) -> dict:+ """FIRST-TIME-USER DEMO: take a brand-new user from nothing to "wow" in one verb.++ Written because HD's installer ran a "demo" that just opened Fusion and SAT on the+ sign-in page doing nothing (John, 2026-07-20). A demo must actually finish the sign-in,+ set up APS, and SHOW the user real work: an electronics PROJECT -> SCHEMATIC -> 2D BOARD+ -> 3D BOARD, plus a live APS cloud search.++ STAGED + RESUMABLE. Each call advances as far as it safely can and returns:+ stage - what it just did / is waiting on+ done - whether the demo finished+ narrate - a first-time-user-friendly line the CALLER should say + toast+ screenshots- images to show the user for this stage+ _hint - exactly what the AI must do next (including nbrowser_* for the browser leg)++ The bridge owns Fusion; it does NOT own the browser. So when the sign-in needs a browser+ we hand the caller precise `nbrowser_*` (ABE) instructions - the user's NATIVE browser is+ already signed into Autodesk, whereas pup is anonymous and would force a fresh login.+ """+ stage = (args.get("stage") or "auto").strip()+ demo_query = args.get("query") or "" # optional: which design to demo+ steps: list = []+ shots: list = []++ def _shot(label):+ try:+ r = _handle_screenshot_fusion({}, {})+ if r.get("success") and r.get("localSafePath"):+ shots.append({"label": label, "path": r.get("localSafePath")})+ except Exception:+ pass++ def _out(stage_name, narrate, hint, done=False, **extra):+ return {"success": True, "demo": True, "stage": stage_name, "done": done,+ "steps": steps, "narrate": narrate, "screenshots": shots,+ "statusVerb": "fusion_demo", "_hint": hint, **extra}++ # ── 1. Fusion present + running ─────────────────────────────────────────────+ rd = _handle_fusion_readiness({}, {})+ if not rd.get("installed"):+ return _out("not_installed",+ "Fusion 360 isn't installed yet - I can install it for you (free trial is plenty for this demo).",+ "OFFER the install, then call fusion_install_fusion (streams the free trial, 10-30 min; "+ "poll fusion_readiness until installed:true), then call fusion_demo again. See the "+ "fusion-onboarding skill.")+ if not rd.get("running"):+ steps.append("launched Fusion")+ _handle_launch({}, {})+ rd = _handle_fusion_readiness({}, {})++ # ── 2. SIGN-IN: finish it, do not sit on it ─────────────────────────────────+ if rd.get("needsSignin"):+ return _out("signin",+ "Fusion needs your Autodesk sign-in. I'll use your own browser - you're probably "+ "already signed in there, so this should take one click.",+ "FINISH THE SIGN-IN - do NOT leave the user staring at this screen. Use the NATIVE "+ "browser (ABE), never pup: pup is anonymous so Autodesk would demand a full login, "+ "while the user's real Chrome/Edge profile is typically ALREADY signed into Autodesk. "+ "SEQUENCE: (1) nbrowser_readiness - if state!='ready', offer the one-time extension "+ "install (installing-the-extension skill); ABE still exposes nb verbs meanwhile. "+ "(2) Click Fusion's 'Sign In' button in the BACKGROUND via desktop_find_control + "+ "desktop_ui_click (never a coordinate click, never steal focus). That fires the OAuth "+ "URL at the DEFAULT browser. (3) If their default browser is the signed-in profile, it "+ "completes itself - just poll fusion_readiness. If it lands logged-out, open the same "+ "auth URL in the signed-in profile with nbrowser_open_window {profile:'chrome:<their "+ "account>'} (nbrowser_profiles lists them) and click 'Allow'/'Open' there. (4) The "+ "handoff back to Fusion is the 'Autodesk Identity Manager' overlay - tick 'Always allow' "+ "+ 'Open'. (5) NEVER type their password or 2FA: if a secret is demanded, "+ "fusion_notify_owner toasts their machine so THEY type it. Sign-in codes expire in ~2 "+ "min - if it expires, click 'Sign In' again for a fresh one. Poll fusion_readiness until "+ "ready:true, then call fusion_demo again. FULL PLAYBOOK: fusion-autodesk-signin skill.",+ needsSignin=True)++ if not rd.get("ready"):+ return _out("waiting",+ "Fusion is starting up - one moment.",+ "Not ready yet (add-in still loading, or a licensing dialog). Poll fusion_readiness; it "+ "auto-resolves seat dialogs. When ready:true, call fusion_demo again. Reason: " ++ str(rd.get("_hint", ""))[:220])+ steps.append("Fusion ready")++ # ── 3. APS: set it up if we can, otherwise SELL it (never skip silently) ─────+ aps_ready = False+ try:+ ap = aps.handle_status({}).get("data", {})+ aps_ready = bool(ap.get("configured") and ap.get("signedIn") and ap.get("tokenLive"))+ except Exception:+ ap = {}+ if not aps_ready and stage != "skip_aps":+ return _out("aps_setup",+ "Next I'll turn on cloud search - it finds any design in your Autodesk cloud in about "+ "two seconds instead of a 30-minute folder crawl. It's a one-time sign-in.",+ "SET APS UP FOR THEM - do not merely mention it. (1) fusion_aps_status for exact state. "+ "(2) If not configured, an admin registers a PKCE app once, then fusion_aps_set_client_id. "+ "(3) fusion_aps_signin - drive it in their NATIVE browser (ABE), same reasoning as the "+ "Fusion sign-in: they're already logged into Autodesk there. (4) Poll fusion_aps_status "+ "until tokenLive:true, then call fusion_demo again - the demo then runs a LIVE sample "+ "search so they SEE the speed. If they decline setup, call fusion_demo {stage:'skip_aps'} "+ "and TELL them what they're missing (2s server-indexed search across the whole team hub; "+ "the old in-app search took 30+ min and crashed Fusion, so it is disabled). "+ "Skills: fusion-aps-search, fusion-aps-signin.",+ apsConfigured=bool(ap.get("configured")), apsSignedIn=bool(ap.get("signedIn")))++ # ── 4. APS sample search - let them SEE the speed ───────────────────────────+ aps_hits = []+ if aps_ready:+ try:+ import time as _t+ t0 = _t.time()+ sr = aps.handle_search({"query": demo_query or "board", "limit": 5}).get("data", {})+ aps_hits = [{"name": r.get("name"), "project": r.get("projectName")}+ for r in (sr.get("results") or [])[:5]]+ steps.append("APS sample search: %d hits in %.1fs" % (len(aps_hits), _t.time() - t0))+ except Exception as e:+ steps.append("APS sample search failed: %s" % e)++ # ── 5. Open an ELECTRONICS design, then walk schematic -> 2D -> 3D ──────────+ st = _proxy_to_addin("get_app_state", {}, timeout=20) or {}+ doc = (st.get("data") or st).get("activeDocument")+ is_elec = bool((st.get("data") or st).get("isElectronics"))+ if not is_elec:+ target = demo_query or (aps_hits[0]["name"] if aps_hits else "")+ if not target:+ return _out("need_design",+ "I need an electronics design to show off. Which board should I open?",+ "No electronics design open and nothing to pick. If APS is live, "+ "fusion_aps_search {query:'<board>'} then fusion_aps_open {query:'<name>'}; else ask "+ "the user for a design name / open one via fusion_open_cloud_file. ALWAYS open the "+ "PROJECT (EcadDesignProductType), never a .brd/.sch/3D child. Then call fusion_demo again.")+ return _out("open_design",+ "Opening %s so you can see a real board end to end." % target,+ "OPEN THE PROJECT then re-call fusion_demo: fusion_aps_open {query:'%s'} (APS finds it at "+ "any folder depth in seconds). CRITICAL: open the electronics PROJECT file, not the "+ "schematic/.brd/3D child - a child opens an isolated, often empty view. Poll "+ "fusion_get_app_state until isElectronics:true, then call fusion_demo again." % target,+ target=target)++ steps.append("electronics project open: %s" % doc)+ _shot("project")++ # schematic -> 2D board -> 3D board, screenshotting each so the AI can SHOW them+ try:+ _proxy_to_addin("show_schematic", {}, timeout=90); steps.append("showed schematic"); _shot("schematic")+ except Exception as e:+ steps.append("schematic failed: %s" % e)+ try:+ _proxy_to_addin("show_2d_board", {}, timeout=90); steps.append("showed 2D board"); _shot("board_2d")+ except Exception as e:+ steps.append("2D board failed: %s" % e)+ try:+ _proxy_to_addin("show_3d_board", {}, timeout=180); steps.append("showed 3D board"); _shot("board_3d")+ except Exception as e:+ steps.append("3D board failed: %s" % e)++ aps_line = ("Cloud search is live - I searched your whole Autodesk hub in about two seconds and "+ "found: %s. " % ", ".join(h["name"] for h in aps_hits[:3])) if aps_hits else ""+ return _out("done",+ "That's the tour: your %s project, its schematic, the 2D board layout, and the real 3D board. "+ "%sFrom here just ask - export Gerbers/BOM/CPL for the fab, generate a laser-etched IPC "+ "package, load JLCPCB design rules, or open any design in your cloud." % (doc, aps_line),+ "DEMO COMPLETE. SHOW the user the screenshots in order (project, schematic, board_2d, "+ "board_3d) - they are in `screenshots` with labels. Narrate the `narrate` line. Then offer "+ "concrete next steps in THEIR words: 'export the Gerbers', 'make me a SOIC-8 with my part "+ "number etched on it' (fusion_generate_package), 'check this against JLCPCB rules' "+ "(fusion_load_design_rules), 'find my other boards' (fusion_aps_search). Full catalog: "+ "fusion_describe. Demo playbook: the fusion-demo skill.",+ done=True, document=doc, apsSampleSearch=aps_hits)++ def _orchestrate_board_stackup(args: dict) -> dict: """Read a board's PHYSICAL fabrication stackup (see the pcb-stackup skill). A PCB is a stack of copper + dielectric: Cu(L1) / prepreg / Cu(L2) / core / ... / Cu(bottom). This@@ -3782,6 +3953,8 @@ def dispatch_command(command: str, args: dict) -> dict: return _orchestrate_export_optimized_glb(args) if command == "fetch_optimized_glb": return _orchestrate_fetch_optimized_glb(args)+ if command == "demo":+ return _orchestrate_demo(args) if command == "board_stackup": return _orchestrate_board_stackup(args)
skills/fusion-demo/SKILL.mdadded+94@@ -0,0 +1,94 @@+---+name: fusion-demo+description: >+ Run a FIRST-TIME-USER demo of the Fusion 360 bridge - the guided tour Hydrogen Desktop's installer+ fires when someone new wants to see what this thing does. Covers the one verb (fusion_demo), the+ staged loop, and the two rules that make or break it: FINISH the Autodesk sign-in (never leave a new+ user parked on the sign-in page) by driving the user's NATIVE browser via ABE/nbrowser_* (already+ signed into Autodesk) instead of pup (anonymous), and SET UP APS cloud search rather than just+ mentioning it, then prove it with a live sample search. Then show real work in order: electronics+ PROJECT -> SCHEMATIC -> 2D BOARD -> 3D BOARD. Trigger words - fusion demo, demo the bridge, show me+ fusion, first time user demo, hd installer demo, demo verb, guided tour, showcase fusion, new user+ onboarding demo, fusion_demo.+---++# Demoing the Fusion bridge to a brand-new user++## Why this exists++HD's installer ran a "demo" that opened Fusion and then **sat on the Autodesk sign-in page doing+nothing** (John, 2026-07-20). A first-time user watched an app open and stall. That is the single+worst first impression this bridge can make, and this skill exists to make it impossible.++**A demo is not "launch the app." A demo finishes the blockers and shows real work.**++## The one verb++```bash+adom-desktop fusion_demo '{}' # start / resume the tour+adom-desktop fusion_demo '{"query":"BQ25792"}' # demo a specific design+adom-desktop fusion_demo '{"stage":"skip_aps"}' # user declined cloud-search setup+```++It is **staged and resumable**. Every call advances as far as it safely can and returns:++| Field | Use it for |+|---|---|+| `stage` | where you are: `not_installed`, `signin`, `aps_setup`, `open_design`, `done`, ... |+| `done` | keep calling `fusion_demo` until this is `true` |+| `narrate` | say this to the user, verbatim-ish. It is written for a newcomer, not an engineer |+| `screenshots` | `[{label,path}]` - SHOW these; labels are `project`, `schematic`, `board_2d`, `board_3d` |+| `steps` | what it actually did, for your own logging |+| `_hint` | the exact next action, including the `nbrowser_*` calls for the browser leg |++Loop: call it, do what `_hint` says, narrate, call it again. Do not improvise a different order.++## Rule 1: FINISH the sign-in, in the user's NATIVE browser++When `stage:"signin"`:++- **Use ABE (`nbrowser_*`), never pup.** pup is an anonymous browser, so Autodesk demands a full+ login with password + 2FA. The user's real Chrome/Edge profile is **typically already signed into+ Autodesk**, so the same flow is one click. `nbrowser_profiles` lists their real profiles; ABE+ exposes these verbs even before the browser extension is installed.+- Click Fusion's **Sign In** in the BACKGROUND (`desktop_find_control` + `desktop_ui_click`), never a+ coordinate click, never steal focus.+- That fires the OAuth at the **default** browser. If that is the signed-in profile it completes+ itself; if it lands logged-out, re-open the auth URL with+ `nbrowser_open_window {profile:"chrome:<their account>"}`.+- The handoff back is the **Autodesk Identity Manager** overlay: tick "Always allow", click "Open".+- **Never type their password or 2FA.** If a secret is demanded, `fusion_notify_owner` toasts their+ machine so they type it. Sign-in codes expire in ~2 minutes; if it expires, click Sign In again for+ a fresh one.++Full detail: the **fusion-autodesk-signin** skill.++## Rule 2: SET UP APS, don't just name-drop it++When `stage:"aps_setup"`, actually configure it (`fusion_aps_status` -> `fusion_aps_set_client_id`+if unconfigured -> `fusion_aps_signin` driven in the native browser -> poll until `tokenLive:true`).+Then the demo runs a **live sample search** so the user watches their whole Autodesk hub return+results in about two seconds.++If they decline, call `fusion_demo {stage:"skip_aps"}` and still TELL them what it is: server-indexed+search across the team hub in seconds. The old in-app search took 30+ minutes and crashed Fusion, so+it is disabled - APS is the only cloud-search path. See **fusion-aps-search**.++## Rule 3: the tour order is fixed++**electronics PROJECT -> SCHEMATIC -> 2D BOARD -> 3D BOARD.** That sequence tells the story of how a+board is actually made, and each step is screenshotted so you can show it. Always open the PROJECT+(`EcadDesignProductType`), never a `.brd`/`.sch`/3D child - a child opens an isolated, often empty+view and the demo looks broken.++## Landing it++Close by offering next steps in the user's own words, not verb names: "export the Gerbers", "make me+a SOIC-8 with my part number etched on it", "check this against JLCPCB rules", "find my other+boards". The full catalog is `fusion_describe`.++## If something is missing++- Fusion not installed -> offer the install, `fusion_install_fusion`, then resume (fusion-onboarding).+- Nothing to open -> ask which board, or `fusion_aps_search` and open the first hit.+- Never end a demo on an error screen. If a stage fails, say what you tried, and offer the next thing.