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 170 file(s)
15 files changed
+66−34
BRIDGE_VERSION+1−1@@ -1 +1 @@-1.11.28+1.11.29
bridge.json+3−1@@ -2,7 +2,7 @@ "manifest_version": 1, "name": "fusion360", "displayName": "Autodesk Fusion 360",- "version": "1.11.28",+ "version": "1.11.29", "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.",@@ -47,12 +47,14 @@ "fusion_assembly_bom", "fusion_attach_3d_package", "fusion_bind_library_3d",+ "fusion_board_bom", "fusion_board_info", "fusion_board_source", "fusion_board_stackup", "fusion_build_library_3d", "fusion_cancel_run", "fusion_capture_library_views",+ "fusion_change_pours", "fusion_check_recovery", "fusion_claim_seat", "fusion_cleanup_cloud_files",
contracts/describe.json+40@@ -477,6 +477,26 @@ "summary": "LOW-LEVEL primitive: binds ONE STEP onto one deviceset. Prefer fusion_create_library with parts[] (which handles one part or many through a single path); reach for this only when you are driving a single bind deliberately. The CORRECT library in ONE call (the Library button's real bar: the 3D chip renders in the Content Manager preview): mints the part's 3D as a cloud f3d (make_3d_package), injects the wip_urn binding into the .lbr ON DISK (packages3d + package3dinstances), and reopens the library. Needs a signed-in Fusion session - the one cloud-dependent step in the wiki-to-EE circle. Autodesk's thumbnail preview lags ~2-3 min behind a fresh mint. NOTE: distinct from the older fusion_build_library_3d (multi-part batch pipeline).", "timeoutSeconds": 480 },+ {+ "example": {},+ "input": {+ "expectDocument": "required exact board name",+ "outputDir": "optional folder on this machine for bom.csv + bom-jlcpcb.csv"+ },+ "longRunning": false,+ "name": "fusion_board_bom",+ "output": {+ "boardOnly": "[str]",+ "csv": "str",+ "files": "{name:path}",+ "jlcpcbCsv": "str",+ "lines": "[{designators,quantity,value,package,mpn,manufacturer,mouser,digikey,lcsc}]",+ "missingPartNumbers": "{mouser,digikey,lcsc:[str]}"+ },+ "statusVerb": "fusion_routing_state",+ "summary": "The bill of materials from the live board's own part attributes: one line per MPN with designators, quantity, value, package, manufacturer and the Mouser, DigiKey and LCSC numbers, plus the JLCPCB form (Comment, Designator, Footprint, LCSC). Board-only parts (test pads) are listed as such, and any part missing a distributor number is named. Read-only; with outputDir it also writes bom.csv and bom-jlcpcb.csv there.",+ "timeoutSeconds": 60+ }, { "example": {}, "input": {},@@ -600,6 +620,26 @@ "summary": "Capture the LIBRARY-EDITOR views EEs trust: the schematic SYMBOL (full pinout), the FOOTPRINT (pads + layer stack), and the COMPONENT/device view (Content Manager: symbol + the package table with the footprint<->package Mapped check + pin/pad counts). The 3D before/after shots don't show these. Requires the .lbr OPEN in the Electronics Library workspace (fusion_open_lbr first). Runs EDIT <pkg>.sym/.pac/.dev + WINDOW FIT + a background hwnd screenshot per view; returns the PNG paths on the box (C:/tmp/conduit-screenshots - pull with desktop_pull_file). EDIT uses the DEVICESET name (e.g. ESP32-S3FN8).", "timeoutSeconds": 300 },+ {+ "example": {},+ "input": {+ "boardId": "required",+ "expectDocument": "required exact board name",+ "expectedRevision": "required",+ "pours": "required [{net, layer, points:[[x,y]...], width? (mm), isolate? (mm)}]"+ },+ "longRunning": false,+ "name": "fusion_change_pours",+ "output": {+ "changes": "[{net,layer,width:[before,after],isolate:[before,after],filledMm2:[before,after]}]",+ "revision": "str",+ "success": "bool",+ "verified": "bool"+ },+ "statusVerb": "fusion_routing_state",+ "summary": "Change existing pours in place: the pen width (the narrowest copper the fill can reach; a pen wider than a throat leaves it empty) and the isolation. Each pour is named by net, layer and outline, picked on the midpoint of its longest edge, then RATSNEST refills. The readback proves each pour took its new width/isolate and that no track or via changed, and reports the filled area before and after.",+ "timeoutSeconds": 120+ }, { "example": { "fileName": "BQ25792",
dashboard/Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "fusion-dashboard"-version = "1.11.28"+version = "1.11.29" dependencies = [ "serde_json", ]
dashboard/Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.11.28"+version = "1.11.29" edition = "2021" [dependencies]
describe.py+6@@ -40,6 +40,12 @@ _T = [ ("fusion_schematic_run", "Build a schematic live: a list of complete, non-interactive EAGLE commands run one at a time on the active schematic (ADD 'dev@lib' 'NAME' R0 (x y), VALUE, NET 'name' (pts), LABEL, WIRE, TEXT, LAYER, CHANGE STYLE/SIZE/WIDTH/RATIO, WINDOW FIT), with an optional pause between them so a viewer sees it grow. Anything else is refused before the first command runs. ADD is proven against libraryPath on disk first (the deviceset must be there; the library is USEd by the bridge), so the component picker can never open. Readback: the parts and nets on the sheet from a fresh export.", {"expectDocument":"optional exact schematic name","libraryPath":"required for ADD: the .lbr on this machine (its file name is the library name in ADD)","commands":"required [command] (1..400)","pauseMs":"optional 0..3000 between commands"}, {"success":"bool","verified":"bool","parts":"[name]","added":"[name]","nets":"{net:[part.pin]}","commands":"int"},120,"fusion_get_app_state",False,{}),+ ("fusion_board_bom", "The bill of materials from the live board's own part attributes: one line per MPN with designators, quantity, value, package, manufacturer and the Mouser, DigiKey and LCSC numbers, plus the JLCPCB form (Comment, Designator, Footprint, LCSC). Board-only parts (test pads) are listed as such, and any part missing a distributor number is named. Read-only; with outputDir it also writes bom.csv and bom-jlcpcb.csv there.",+ {"expectDocument":"required exact board name","outputDir":"optional folder on this machine for bom.csv + bom-jlcpcb.csv"},+ {"lines":"[{designators,quantity,value,package,mpn,manufacturer,mouser,digikey,lcsc}]","csv":"str","jlcpcbCsv":"str","files":"{name:path}","boardOnly":"[str]","missingPartNumbers":"{mouser,digikey,lcsc:[str]}"},60,"fusion_routing_state",False,{}),+ ("fusion_change_pours", "Change existing pours in place: the pen width (the narrowest copper the fill can reach; a pen wider than a throat leaves it empty) and the isolation. Each pour is named by net, layer and outline, picked on the midpoint of its longest edge, then RATSNEST refills. The readback proves each pour took its new width/isolate and that no track or via changed, and reports the filled area before and after.",+ {"expectDocument":"required exact board name","boardId":"required","expectedRevision":"required","pours":"required [{net, layer, points:[[x,y]...], width? (mm), isolate? (mm)}]"},+ {"success":"bool","verified":"bool","changes":"[{net,layer,width:[before,after],isolate:[before,after],filledMm2:[before,after]}]","revision":"str"},120,"fusion_routing_state",False,{}), ("fusion_board_source", "Read the live board as EAGLE XML from a fresh export: parts, copper, vias, pours with Fusion's own computed fill, and the outline. Read-only. Feed it to adom-fields (it reads .brd) for current and heat, or to adom-aiflow, which converts it for its offline checks.", {"expectDocument":"required exact board name","boardId":"optional"}, {"source":"str (EAGLE .brd XML)","boardId":"str","revision":"str"},60,"fusion_routing_state",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.11.28"+DASH_VERSION="1.11.29" 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.11.28",+ "version": "1.11.29", "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+10−26@@ -1,6 +1,6 @@ { "slug": "fusion-bridge",- "version": "1.11.28",+ "version": "1.11.29", "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",@@ -76,6 +80,9 @@ "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", "aps not configured", "share aps client id across my org", "set up fusion cloud search for my company",@@ -108,28 +115,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.11.28"+version = "1.11.29" edition = "2021" license = "MIT"
rust/bridge/src/routing.rs+1−1@@ -2,7 +2,7 @@ //! script transport. Embedding the implementation avoids replacing a loaded add-in. use serde_json::{json, Value}; const SOURCE: &str = concat!(include_str!("routing_script.py"), "\n", include_str!("routing_planner.py"));-pub fn owns(cmd: &str) -> bool { matches!(cmd, "routing_state" | "route_net" | "routing_drc" | "plan_route" | "move_parts" | "place_vias" | "apply_pours" | "pour_state" | "board_source" | "ripup_nets" | "schematic_run") }+pub fn owns(cmd: &str) -> bool { matches!(cmd, "routing_state" | "route_net" | "routing_drc" | "plan_route" | "move_parts" | "place_vias" | "apply_pours" | "pour_state" | "board_source" | "ripup_nets" | "schematic_run" | "board_bom" | "change_pours") } pub fn call(cmd: &str, args: &Value, pass: &dyn Fn(&str, Value) -> Value) -> Value { let script = format!("import json\nexec({})\nresult=handle(app,json.loads({}),{})\n", serde_json::to_string(SOURCE).unwrap(),
tools/check-naming.shtools/check-portable.shtools/promote.shtools/release.sh