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 163 file(s)
16 files changed
+134−37
BRIDGE_VERSION+1−1bridge.json+1−1contracts/describe.json+1−1dashboard/Cargo.lock+1−1dashboard/Cargo.toml+1−1describe.py+1−1install.sh+1−1package.json+1−1page.json+11−27rust/Cargo.toml+1−1rust/bridge/src/main.rs+10−1skills/fusion-contributing/SKILL.md+104tools/check-naming.shtools/check-portable.shtools/promote.shtools/release.shBRIDGE_VERSION+1−1@@ -1 +1 @@-1.10.18+1.10.19
bridge.json+1−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.10.18",+ "version": "1.10.19", "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.",
contracts/describe.json+1−1@@ -778,7 +778,7 @@ "verbs": "[{name,summary,input,output,timeoutSeconds,statusVerb,longRunning,example}]" }, "statusVerb": null,- "summary": "Self-describe every verb the bridge exposes (this list) for ab's Verbs tab + runner.",+ "summary": "Self-describe every verb the bridge exposes (this list) for ab's Verbs tab + runner. The reply carries `contribute` (source, mirror, issue and PR commands, the fusion-contributing skill); every failing reply carries `_contribute` with the same pointer.", "timeoutSeconds": 20 }, {
dashboard/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "fusion-dashboard"-version = "1.10.18"+version = "1.10.19" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.10.18"+version = "1.10.19" edition = "2021" [dependencies]
describe.py+1−1@@ -411,7 +411,7 @@ _T = [ 60, None, False, {"fileName": "BQ25792", "projectName": "Main", "folderPath": "Molecules/XRP/Power"}), # ── Self-describe ──────────────────────────────────────────────────────- ("fusion_describe", "Self-describe every verb the bridge exposes (this list) for ab's Verbs tab + runner.",+ ("fusion_describe", "Self-describe every verb the bridge exposes (this list) for ab's Verbs tab + runner. The reply carries `contribute` (source, mirror, issue and PR commands, the fusion-contributing skill); every failing reply carries `_contribute` with the same pointer.", {}, {"success": "bool", "verbs": "[{name,summary,input,output,timeoutSeconds,statusVerb,longRunning,example}]"}, 20, None, False, {}), ]
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.10.18"+DASH_VERSION="1.10.19" 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.10.18",+ "version": "1.10.19", "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−27@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.10.18",+ "version": "1.10.19", "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,28 +111,5 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ],- "agent_permissions": {- "allow_bash": [],- "allow": [- "adom-desktop-fusion-bridge read-only verbs (via the adom-bridge CLI): fusion_readiness, fusion_get_app_state, fusion_addin_status, fusion_check_dialogs - state queries; they change nothing.",- "adom-desktop-fusion-bridge read-only verbs: fusion_alerts (reads Fusion's own log for toasts), fusion_document_info, fusion_window_info, fusion_board_info, fusion_library_parts - inspect only.",- "adom-desktop-fusion-bridge read-only verbs: fusion_prove_result (a persisted run report), fusion_plan_library_import (report-only preflight), fusion_list_cloud_projects, fusion_describe.",- "adom-desktop-fusion-bridge evidence captures fusion_screenshot_fusion and fusion_capture_library_views read pixels and write local image files only."- ],- "soft_deny": [- "adom-desktop-fusion-bridge lifecycle verbs fusion_stop, fusion_kill, fusion_restart_for_addin close or kill the Fusion application - keep the human prompt.",- "adom-desktop-fusion-bridge fusion_install_fusion silently installs Autodesk Fusion on the user's machine.",- "adom-desktop-fusion-bridge fusion_cleanup_cloud_files deletes files from the user's Autodesk cloud hub.",- "adom-desktop-fusion-bridge managed-library verbs (fusion_managed_library_push/pull/create/link/unlink) publish to or overwrite the user's library.io libraries."- ],- "environment": [- "adom-desktop-fusion-bridge is the Fusion 360 bridge for Adom Bridge; its fusion_* verbs are invoked through the adom-bridge CLI and drive Autodesk Fusion on the user's own desktop.",- "adom-desktop-fusion-bridge desktop actions also pass Adom Bridge's own human-approval gate (caller identity, per-call reason, Activity Log) - a container approval is the first of two gates."- ]- },- "author": {- "name": "John Lauer",- "email": "[email protected]"- }-}+ ]+}
rust/Cargo.toml+1−1@@ -4,7 +4,7 @@ members = ["core", "lbr", "os-win", "os-mac", "bridge"] # One version for the whole bridge, in lockstep with BRIDGE_VERSION (tools/release.sh bumps both). [workspace.package]-version = "1.10.18"+version = "1.10.19" edition = "2021" license = "MIT"
rust/bridge/src/main.rs+10−1@@ -439,7 +439,10 @@ fn main() { "fusion_describe" | "describe" => { let c: Value = serde_json::from_str(fusion_core::contract::FROZEN).unwrap_or(json!({})); let verbs = c["verbs"].clone(); let n = verbs.as_array().map(|a| a.len()).unwrap_or(0);- json!({"success": true, "bridge": "fusion360", "verbCount": n, "verbs": verbs, "data": {"bridge": "fusion360", "verbCount": n, "verbs": c["verbs"]}, "shell": "rust"}) },+ json!({"success": true, "bridge": "fusion360", "verbCount": n, "verbs": verbs, "data": {"bridge": "fusion360", "verbCount": n, "verbs": c["verbs"]}, "shell": "rust",+ "contribute": {"source": "https://wiki.adom.inc/adom/fusion-bridge (the wiki page is the repo: adom-wiki repo clone adom/fusion-bridge)", "mirror": "a GitHub mirror under adom-inc, linked from the page; the wiki repo is canonical",+ "issues": "adom-wiki issue create adom/fusion-bridge --category bug-report (include the reply JSON)", "pullRequests": "adom-wiki branch create / repo push --branch / pr create --from",+ "skill": "fusion-contributing", "note": "A verb you had to work around is a bug report or a PR; both are welcome and merge fast with evidence."}}) }, "fusion_close_window" | "close_window" if addin_owner_is_exe(&**h) => { let mut r = small_verbs::close_window(&parsed["args"], &caller); r["shell"] = json!("rust"); r }, "fusion_screenshot_fusion" | "screenshot_fusion" if addin_owner_is_exe(&**h) => { let mut r = small_verbs::screenshot_fusion(&parsed["args"], &caller); r["shell"] = json!("rust"); r }, "fusion_dismiss_blocking_dialogs" | "dismiss_blocking_dialogs" if addin_owner_is_exe(&**h) => {@@ -503,6 +506,12 @@ fn main() { "_hint": "Rust plumbing shell; every catalogued verb is served, natively or via the Python sidecar."}), _ => proxy(&sidecar, &raw, &caller), };+ // every failure points at the source: the bridge is open, the wiki page is the+ // repo, and a workaround an AI had to invent is a contribution (John, 2026-09-19)+ let mut reply = reply;+ if reply.is_object() && reply["success"].as_bool() == Some(false) && reply["_contribute"].is_null() {+ reply["_contribute"] = json!("If this is a bridge defect or a gap, the source is open: adom-wiki repo clone adom/fusion-bridge (the wiki page is the repo; a GitHub mirror is linked from the page). File it with this reply JSON (adom-wiki issue create adom/fusion-bridge) or fix it and send a PR (adom-wiki pr create). The fusion-contributing skill has the steps, including trying your build on your own box behind a dev pin.");+ } let _ = req.respond(json_response(200, &reply)); } _ => { let _ = req.respond(json_response(404, &json!({"error": "not found"}))); }
skills/fusion-contributing/SKILL.mdadded+104@@ -0,0 +1,104 @@+---+name: fusion-contributing+public: true+description: "How to contribute to the Fusion bridge when you hit a bug, a missing verb, a wrong hint or a dialog the bridge cannot answer: where the source lives (the wiki page IS the repo), how to file the issue with the evidence, clone the source, make the change (dialog rules, hints, verbs, skills, the exe), build and try it on your own box behind a dev pin, and send a pull request back with adom-wiki. Read this the moment an AI has to WORK AROUND the bridge instead of using it. Trigger words: contribute, contribute back, send a PR, pull request, patch the bridge, modify the bridge, fix the bridge myself, bridge source code, where is the source, clone the bridge, add a dialog rule, add a verb, fix a hint, fork the bridge, community contribution, work around a bridge bug, bridge bug."+---++# Contributing to the Fusion bridge++The Fusion bridge is open. Its wiki page is the repository: every release pushes the whole+source tree (the Rust exe, the Fusion add-in, the verb contract, the skills, the tests) to+[adom/fusion-bridge](https://wiki.adom.inc/adom/fusion-bridge), and pull requests are reviewed+there. A GitHub mirror under adom-inc is linked from the page; the wiki repo is canonical. If your AI just worked+around the bridge instead of using it, that workaround is a contribution waiting to happen:+file it, or fix it and send the change back. Both take minutes with the `adom-wiki` CLI you+already have.++## 1. Report first (two minutes, always worth it)++```bash+adom-wiki issue create adom/fusion-bridge --category bug-report \+ --title "<verb>: <what happened in one line>" \+ --body-file report.md+```++Put in `report.md`: the exact call and its full reply JSON (the `_hint` and `errorCode`+matter), `fusion_readiness` output (bridge version, add-in version, box), the Fusion build,+what you expected, and the workaround you used. Attach a screenshot or the exported board if+one exists. A report with the reply JSON is usually fixed the same day; the maintainer thread+answers on the issue.++## 2. Get the source++```bash+adom-wiki repo clone adom/fusion-bridge --dir fusion-bridge # HEAD of master, files only+cd fusion-bridge+```++Where things live:++| Path | What it is |+|---|---|+| `rust/bridge/src/` | the exe ab spawns (`adom-fusion-bridge.exe`): verb dispatch in `main.rs`, the pass-through envelope in `addin.rs`, dialogs and restarts in `lifecycle.rs`, chains in `chains.rs`, APS search in `main.rs`, staging in `fusionpath.rs` |+| `rust/core/src/` | shared logic: `dialog_rules.json` (dialog text to category and resolution), readiness, window facts, APS |+| `addin/AdomBridge/` | the Python add-in that runs inside Fusion: one handler per verb under `commands/`, registered in `commands/__init__.py` |+| `describe.py` and `contracts/describe.json` | the verb contract `fusion_describe` serves; `tools/freeze-contract.py` regenerates the JSON |+| `skills/` | the user skills the package installs (this file is one) |+| `tests/run_verb_tests.py` | the daily verb test; every described verb must be triaged there or the run goes red |+| `CHANGELOG.md` | newest first; every change gets an entry |++## 3. The common contributions++- **A dialog the bridge could not answer** (the reply was `blocked_by_dialog` with the box's+ text and buttons): add a rule to `rust/core/src/dialog_rules.json` (`needles` from the text,+ a `category`, a `resolution` that names the safe button) and the parity entry in+ `handlers/dialog_classify.py`; add a case to the tests in `rust/core/src/dialogs.rs`.+- **A wrong or missing hint**: hints are plain strings next to the reply that carries them+ (`_hint` in the Rust or the Python handler). Say what to do next, not what went wrong twice.+- **A new verb**: a handler in `addin/AdomBridge/commands/`, its name in+ `commands/__init__.py`, in `ADDIN_COMMANDS` in `rust/bridge/src/addin.rs`, an entry in+ `describe.py`, then `python3 tools/freeze-contract.py`, and a `t(...)` line in+ `tests/run_verb_tests.py`.+- **A skill**: a folder under `skills/<name>/SKILL.md` with frontmatter (`name`, `public`,+ `description` with the trigger words users actually say).++## 4. Build and try it on your own box++Prerequisites once: Rust stable, the cross target and MinGW for the Windows exe.++```bash+rustup target add x86_64-pc-windows-gnu+sudo apt-get install -y mingw-w64 # Linux or WSL; on Windows build natively+cd rust && cargo test -p adom-fusion-bridge # unit tests, including the dialog rules+cargo build --release --target x86_64-pc-windows-gnu -p adom-fusion-bridge+```++Try it without touching the released install: pin the bridge cache on the box so ab stops+updating it, copy your build in, let ab respawn it, and unpin when you are done.++```bash+adom-bridge --target <box> --ai-thread <you> bridge_dev_mode '{"name":"fusion360","on":true}'+adom-bridge --target <box> --ai-thread <you> send_files '{"filePaths":["rust/target/x86_64-pc-windows-gnu/release/adom-fusion-bridge.exe"],"dest":"C:/Users/<user>/AppData/Local/Adom Bridge/bridges-cache/fusion360"}'+adom-bridge --target <box> --ai-thread <you> fusion_readiness '{}' # bridgeVersion is your build+adom-bridge --target <box> --ai-thread <you> bridge_dev_mode '{"name":"fusion360","on":false}' # when done+```++An add-in change (`addin/`) also needs the add-in folder copied into the cache and a Fusion+restart (`fusion_restart_for_addin {save:true}`), because Fusion loads add-ins at launch.++## 5. Send the pull request++```bash+adom-wiki branch create adom/fusion-bridge fix/<short-name>+adom-wiki repo push adom/fusion-bridge --branch fix/<short-name> \+ --message "<what and why, one line>" --files <the files you changed>+adom-wiki pr create adom/fusion-bridge --from fix/<short-name> \+ --title "<what it fixes>" --body-file pr.md+```++In `pr.md`: the issue it answers, what changed, and how you verified it (box, Fusion build,+the verb call and its reply before and after). Add a CHANGELOG entry at the top of+`CHANGELOG.md` under the next version. House style: plain sentences, no em-dashes. The+maintainer thread reviews, merges into master (a true merge, history kept) and ships it in the+next insiders release, then public after the pre-production gate; you will see the version on+the issue. A PR that comes with its evidence merges fast.
tools/check-naming.shtools/check-portable.shtools/promote.shtools/release.sh