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 MAKING_LIBRARIES.md (full symbol+footprint+3D pipeline, screenshots, every verb) + fusion-libraries skill + open_lbr 3D-pitfall hints
7 files changed
+199−3
MAKING_LIBRARIES.mdadded+116@@ -0,0 +1,116 @@+# Making component libraries in Fusion 360 (symbol + footprint + 3D)++How an Adom component library is built and gets into Fusion 360 Electronics as a placeable part,+captured end to end on a real part (Nordic **nRF54L15**). It covers the parts that work today and+the one hard step that is still being automated: attaching the real 3D chip via a Fusion cloud URN.++> Companion skill: `skills/fusion-libraries/SKILL.md`. Verb reference: [VERBS.md](VERBS.md).++## The pipeline++```+chip-fetcher -> adom-symbol -> NAME.kicad_sym ┐+(vendor bundle) adom-footprint -> NAME.kicad_mod ┼-> adom-lbr generate -> NAME.lbr -> fusion_open_lbr+ incl 3D/NAME.stp + NAME.glb ┘ (symbol + package + connects) (Library editor)+ (2D; 3D = placeholder)+ then: STEP -> Fusion cloud (URN) -> 3D Package Generator -> real 3D on the package+```++| Tool | Role | Output |+|---|---|---|+| **chip-fetcher** | pulls a multi-CAD vendor bundle for an MPN; the content source | `library/<MPN>/<MPN>.step`, `.glb`, vendor EAGLE/KiCad |+| **adom-symbol** | builds the schematic symbol | `NAME.kicad_sym` (2D, no 3D) |+| **adom-footprint** | builds the PCB footprint | `NAME.kicad_mod` (2D, no 3D) |+| **adom-lbr** | assembles + validates the EAGLE library | `NAME.lbr` (symbol + package + deviceset) |++`adom-lbr generate --sym NAME.kicad_sym --fp NAME.kicad_mod -o NAME.lbr` then+`adom-lbr validate NAME.lbr` -> "valid EAGLE .lbr with complete deviceset".++## Step 1 - open the .lbr in Fusion++The `.lbr` is built in the cloud container; Fusion runs on Windows. There is **no container-to-Windows+push verb**, so stage the file first, then open the Windows path.++```bash+# serve from the container+cd <dir-with-lbr> && python3 -m http.server 8931+# download onto Windows (build the JSON in Python; Windows paths need \\ )+adom-desktop shell_execute '{"command":"powershell -NoProfile -Command \"Invoke-WebRequest -Uri https://<workspace>.adom.cloud/proxy/8931/NAME.lbr -OutFile C:\\Users\\<user>\\adom-lib\\NAME.lbr\""}'+# open it+adom-desktop fusion_open_lbr '{"filePath":"C:/Users/<user>/adom-lib/NAME.lbr","verify":true}'+adom-desktop fusion_get_app_state '{}' # expect activeWorkspace "Electronics Library", isElectronics true+```++The library loads with symbol + footprint + deviceset. The 3D package is a **placeholder** (the Content+Manager 3D tab is empty). This is correct, and is the gap the rest of this guide closes.++++## Step 2 - put the 3D model in the Fusion cloud (get a URN)++Fusion does NOT embed the STEP in the `.lbr`. A package references its 3D model by a Fusion cloud+**file URN** (`urn:adsk.wipprod:fs.file:vf.<id>?version=N`). So the model has to live in the cloud+first. Stage the STEP to Windows (same as step 1), then upload it:++```bash+adom-desktop fusion_aps_browse '{}' # find hub + project+adom-desktop fusion_aps_browse '{"projectId":"<proj>"}' # find the root folder+adom-desktop fusion_aps_create_folder '{"projectId":"<proj>","parentFolderId":"<root>","name":"Electronics 3D"}'+adom-desktop fusion_aps_upload '{"projectId":"<proj>","folderId":"<folder>","localPath":"C:/Users/<user>/adom-lib/NAME.step","fileName":"NAME-3D.step"}'+# -> { "itemUrn": "urn:adsk.wipprod:dm.lineage:...", "bytes": ... }+```++Verified on nRF54L15: the STEP (1088914 bytes) uploaded into `Standard Components / Electronics 3D`+and returned a real URN. (`Electron.getCloudPathFromUrn` confirms the 3D package references a Fusion+**file** URN, which is what this path produces.)++## Step 3 - the 3D Package Generator (attach the model to the footprint)++Fusion exposes a scriptable entry point:++```bash+adom-desktop fusion_execute_text_command '{"command":"Electron.Create3DPackage C:/Users/<user>/adom-lib/NAME.lbr"}'+```++This opens the **3D PACKAGE Generator**: a Design-workspace authoring document with the footprint+loaded (the green courtyard + `>NAME` / `>VALUE`), and a PACKAGE / SELECT / FINISH ribbon.++++In the generator you (a) **PACKAGE -> insert the 3D model**, (b) position it over the footprint, and+(c) **FINISH**, which pushes the 3D package back to the library and writes the `package3d` URN.++### Status of the last mile (being honest)++The insert + FINISH actions are **UI-only**: Fusion exposes them through neither a text command+(`fusion_list_text_commands` has `Electron.Create3DPackage` but nothing to insert a model or finish)+nor a routed bridge verb (`fusion_import_file` is not exposed). So completing the attach today means+either driving the Qt ribbon (UIA does not surface those collapsed menu items cleanly) or adding a new+bridge add-in command that does the association through Fusion's Library/Package API. That verb+(`fusion_attach_3d_package`) is the next build; everything up to it is proven above.++## Pitfalls++- **Container path to `fusion_open_lbr`/upload** fails - paths must be Windows-local; stage first.+- **Assuming the 3D is there** - adom-lbr output is 2D; the package is a placeholder until step 3 completes.+- **`Electron.Create3DPackage` with no/blank args** opens a stray "Untitled" (or footprint-named) Design;+ close it with `fusion_close_document '{"save":false}'` if you abandon the generator.+- **Guessing the `package3d` XML** - no on-disk example exists (not even vendor EAGLE downloads carry 3D);+ the markup is generated by Fusion. Reverse-engineer from a real FINISH before writing any.+- **`desktop_screenshot_window` needs `hwnd`** (resolve via `desktop_find_window`) and returns inline base64.++## Every verb used in this sequence++| Verb | What it did here |+|---|---|+| `adom-lbr generate` / `validate` | build + validate `NAME.lbr` |+| `shell_execute` (PowerShell `Invoke-WebRequest`) | stage `.lbr` / `.step` onto Windows |+| `fusion_open_lbr` | open the library in the Electronics Library editor |+| `fusion_get_app_state` | confirm active doc / workspace / isElectronics |+| `desktop_find_window` + `desktop_screenshot_window` | capture the Fusion window |+| `fusion_aps_browse` | find the hub / project / root folder |+| `fusion_aps_create_folder` | make the `Electronics 3D` folder |+| `fusion_aps_upload` | upload the STEP to the cloud, return the URN |+| `fusion_list_text_commands` | discover `Electron.Create3DPackage` / `getCloudPathFromUrn` |+| `fusion_execute_text_command` | run `Electron.Create3DPackage <footprint>` |+| `fusion_close_document` | close the generator / stray designs |
README.md+2@@ -52,6 +52,8 @@ Capture with WGC (`desktop_record_window_start`) - it grabs the live editor canv **Full verb reference:** every verb with its input/output schema and examples is in **[`VERBS.md`](VERBS.md)** (generated from the bridge's own `fusion_describe`). +**Building component libraries** (symbol + footprint + 3D into a placeable `.lbr`, with the chip-fetcher / adom-symbol / adom-footprint / adom-lbr pipeline and the 3D-via-cloud-URN flow): see **[`MAKING_LIBRARIES.md`](MAKING_LIBRARIES.md)**.+ ## ⚡ Fast cloud search (APS) — find any team design in seconds Searching your Fusion 360 cloud files the normal way (the in-app data API) takes **30+ minutes** on a real team hub — it has to walk folders one at a time. This bridge instead queries **Autodesk Platform Services (APS)**, Autodesk's **server-side index**, so the same search returns in **seconds**. Live-proven: searching "Molecule" across a 16-project hub returned 37 real files in ~12 seconds.
describe.py+3−3@@ -71,9 +71,9 @@ _T = [ ("fusion_open_by_urn_note", "(see fusion_open_by_urn)", {}, {}, 30, None, False, {}), ("fusion_board_info", "Raw board geometry XML (copper/arcs/lines) for the open board.", {}, {"rawXml": "str"}, 60, None, False, {}),- ("fusion_open_lbr", "Import an EAGLE .lbr library into Fusion's Electronics library editor.",- {"filePath": "required str (.lbr on the machine)", "symbolName": "optional str", "verify": "optional bool"},- {"success": "bool", "postOpenScreenshot": "{savedTo}"}, 50, None, False, {"filePath": "C:/libs/nRF52840-CKAA.lbr"}),+ ("fusion_open_lbr", "Import an EAGLE .lbr library into Fusion's Electronics LIBRARY editor (Content Manager / Electronics Library workspace), not a PCB design. PITFALL: filePath MUST be a WINDOWS-local path (C:/...). The chip-fetcher/adom-lbr pipeline runs in the cloud container, and there is NO container-to-Windows push verb, so STAGE the .lbr onto Windows first (serve it on a proxied port + Invoke-WebRequest via shell_execute), then pass the C:/ path. PITFALL: an adom-lbr .lbr is 2D ONLY - symbol + footprint + a PLACEHOLDER 3D package; the real 3D chip is NOT attached (that needs a Fusion cloud URN). To attach the 3D, see the 'fusion-libraries' skill. Pass verify:true to round-trip-confirm Fusion parsed the deviceset, then check fusion_get_app_state (activeWorkspace 'Electronics Library').",+ {"filePath": "required str (.lbr WINDOWS path C:/...; stage from container first)", "symbolName": "optional str", "verify": "optional bool"},+ {"success": "bool", "postOpenScreenshot": "{savedTo}"}, 50, None, False, {"filePath": "C:/Users/<user>/adom-lib/nRF54L15.lbr"}), ("fusion_run_modeling_script", "Run an adsk.fusion modeling script in the live session (sketches/extrudes/params). Free programmatic CAD.", {"script": "required str (Python using adsk; globals: adsk, app, ui, design)"}, {"result": "obj", "documentName": "str"}, 180, None, True, {"script": "import adsk.fusion\n# ...build geometry..."}),
lib-01-open.pngadded⋯ 1 unchanged line ⋯
lib-02-generator.pngadded⋯ 1 unchanged line ⋯
server.py+6@@ -1001,6 +1001,12 @@ def _orchestrate_open_lbr(args: dict) -> dict: "success": True, "output": f"Opened library: {os.path.basename(file_path)}", "data": {"results": results, "filePath": file_path},+ "_hint": (+ "Library opened in the Electronics Library editor (Content Manager). "+ "NOTE: an adom-lbr .lbr is 2D ONLY - symbol + footprint + a PLACEHOLDER 3D package. "+ "The real 3D chip is NOT attached; that requires uploading the model to the Fusion "+ "cloud for a URN and linking it. See the 'fusion-libraries' skill before claiming the 3D is present."+ ), } if symbol_name: response["data"]["symbolName"] = symbol_name
skills/fusion-libraries/SKILL.mdadded+72@@ -0,0 +1,72 @@+---+name: fusion-libraries+description: How an Adom component library (symbol + footprint + 3D chip) is built and gets into Fusion 360 Electronics as a placeable .lbr. Covers the full pipeline (chip-fetcher -> adom-symbol / adom-footprint -> adom-lbr -> fusion_open_lbr), the Windows file-staging gotcha (there is NO container-to-Windows push verb), and the hard, still-open problem of attaching the real 3D chip via a Fusion cloud URN. Read before building or opening any library, or when a part shows only a placeholder 3D package. Trigger words - lbr, eagle library, fusion library, open lbr, chip-fetcher, adom-lbr, adom-symbol, adom-footprint, kicad_sym, kicad_mod, deviceset, package3d, 3d package, 3d chip, wipUrn, attach 3d model, placeholder package, content manager, library into fusion, get library into fusion.+---++# Fusion libraries - symbol + footprint + 3D into a placeable .lbr++## 1. The pipeline (where each tool fits)++```+chip-fetcher -> adom-symbol -> .kicad_sym ┐+(vendor bundle) adom-footprint -> .kicad_mod ┼-> adom-lbr generate -> NAME.lbr -> fusion_open_lbr+ (3D STEP/glb provided) ┘ (2D: symbol+package+connects) (Content Manager)+```++- **chip-fetcher** pulls a multi-CAD vendor bundle for an MPN (EAGLE, KiCad, Altium, ... AND a `3D/<MPN>.stp` STEP plus a `.glb`). Its library lives at `chip-fetcher/library/<MPN>/` (e.g. `nRF54L15.step`, `nRF54L15.glb`). chip-fetcher runs as a live app (the viewer is the `chip-fetcher` pup session); it is the content source.+- **adom-symbol** (`adom-symbol create` / `render-ds2sf`) makes the schematic **symbol** as a `.kicad_sym`. It is symbol-only: it does NOT touch STEP, 3D, or URNs.+- **adom-footprint** (`adom-footprint create` / `render-ds2sf`) makes the PCB **footprint** as a `.kicad_mod`. Footprint/2D-only, no 3D.+- **adom-lbr generate** `--sym NAME.kicad_sym --fp NAME.kicad_mod -o NAME.lbr` assembles the EAGLE `.lbr`: `<symbol>` + `<package>` (2D footprint) + `<deviceset>` with the connects. **It is 2D-only** (its `_fp_content`/3D path is unimplemented). The package it writes is a **placeholder** for 3D (see section 4). Validate with `adom-lbr validate NAME.lbr` -> "valid EAGLE .lbr with complete deviceset".+- **fusion_open_lbr** imports the `.lbr` into Fusion's Electronics **Library editor** (Content Manager). You then see the deviceset / symbol / package, and can place the part.++## 2. Opening a .lbr in Fusion (verified working)++`fusion_open_lbr {"filePath": "C:/Users/<user>/.../NAME.lbr", "verify": true}`++- Under the hood it runs `Document.newDesignFromLocal <path>`, which opens the library and switches to the **Electronics Library** workspace.+- `verify:true` re-exports the loaded library to an EAGLE script and returns a preview - proof Fusion actually parsed the deviceset (layers/symbol/package), not just that a window opened.+- After it returns, confirm with `fusion_get_app_state`: expect `activeDocument: NAME`, `activeWorkspace: "Electronics Library"`, `isElectronics: true`. Then screenshot the Fusion window (`desktop_find_window {titleContains:"Fusion"}` -> hwnd -> `desktop_screenshot_window {hwnd}`) to show it.++## 3. THE WINDOWS-STAGING GOTCHA (read this first)++`fusion_open_lbr` (and `fusion_import_file`) take a **filePath on the WINDOWS machine** where Fusion runs (`C:/...`). The whole chip-fetcher/adom-lbr pipeline runs in the **cloud container**, so the `.lbr` / `.step` is on the Linux box, which Fusion cannot read. **There is NO container-to-Windows push verb** (`desktop_pull_*` only goes Windows -> container).++Stage the file onto Windows first. Proven method (same proxy that serves shotlog):++1. Serve it from the container: `cd <dir> && python3 -m http.server 8931` (any proxied port).+2. Download on Windows via `shell_execute`:+ `powershell -NoProfile -Command "New-Item -ItemType Directory -Force -Path C:\Users\<user>\adom-lib | Out-Null; Invoke-WebRequest -Uri 'https://<workspace>.adom.cloud/proxy/8931/NAME.lbr' -OutFile 'C:\Users\<user>\adom-lib\NAME.lbr'"`+3. Open the Windows path with `fusion_open_lbr`.++Confirm the byte count matches after download. Build the `shell_execute` JSON in Python (`json.dumps`), not by hand - nested cmd/PowerShell quoting mangles easily, and Windows paths need `\\` in JSON.++## 4. THE HARD ONE: attaching the real 3D chip (the open problem)++A fresh `.lbr` shows the package as a **placeholder** 3D (the Content Manager 3D tab is empty / a generated box). The real chip STEP exists (`chip-fetcher/library/<MPN>/<MPN>.step`) but is **not linked**. This is the part that "has always been complex."++**Why it is hard:** Fusion does NOT embed the STEP in the `.lbr`. A library package references its 3D model by a **Fusion cloud URN**, not a local file. The model must first exist in the Fusion cloud as a URN-addressed asset, and only then can a `package3d` reference point at it. Format of the URN (from the bridge's cloud code):++```+urn:adsk.wipprod:fs.file:vf.<id>?version=<N>+```++**The verified flow (proven on nRF54L15; full walkthrough + screenshots in [MAKING_LIBRARIES.md](../../MAKING_LIBRARIES.md)):**+1. **Model -> cloud -> URN.** Stage the STEP to Windows, then `fusion_aps_upload {projectId, folderId, localPath:"C:/.../<MPN>.step"}` returns a real cloud URN (`urn:adsk.wipprod:dm.lineage:...`). `Electron.getCloudPathFromUrn` confirms the 3D package references a Fusion **file** URN, which this produces. (`fusion_import_file` is NOT a routed verb; do not rely on it.)+2. **Open the generator.** `fusion_execute_text_command {"command":"Electron.Create3DPackage C:/.../<MPN>.lbr"}` opens the **3D PACKAGE Generator**: a Design-workspace doc with the footprint loaded and a PACKAGE / SELECT / FINISH ribbon.+3. **Insert model + FINISH** -> Fusion writes the `package3d` URN back to the library.++**What is NOT solved yet (the last mile):**+- Step 3's insert + FINISH are **UI-only**: no text command (`fusion_list_text_commands` has `Create3DPackage` but nothing to insert a model or finish) and no routed verb. Completing it today needs either Qt-ribbon UI driving (UIA does not surface those collapsed menu items cleanly) or a **new bridge add-in command (`fusion_attach_3d_package`)** that does the association through Fusion's Library/Package API. That verb is the next build.+- There is still **no on-disk example** of a `.lbr` with a real `package3d` URN (not even vendor EAGLE downloads carry 3D); the markup is generated by the FINISH, so reverse-engineer it from one real FINISH before writing any by hand.++Uploading models into the user's Fusion cloud is an outward, persistent action - confirm first, and put uploads in a contained folder (we used `Standard Components / Electronics 3D`).++## 5. Pitfalls (each one bit us)++- **Container path passed to `fusion_open_lbr`** -> "file not found" / silent fail. The path must be Windows-local; stage it first (section 3).+- **Opening a child instead of a library** - a `.lbr` is a library, not an electronics design; it opens into the **Electronics Library** workspace, not the PCB editor. (Different from the project/schematic/board hierarchy - see the `fusion-electronics` skill.)+- **Assuming the 3D is there** - adom-lbr output is 2D; the package is a placeholder. A part "looking amazing" in symbol+footprint still has NO 3D chip until the URN is linked (section 4).+- **Guessing the `package3d` XML** - no confirmed example exists; reverse-engineer it from a real Fusion-made attachment before writing any.+- **Hand-built `shell_execute` quoting** - use `json.dumps`; escape Windows `\` as `\\` in the JSON.+- **`desktop_screenshot_window` needs `hwnd`** (not `titleContains`); resolve it via `desktop_find_window` first. It returns the PNG as inline base64 - decode to a file.+- **`adom-lbr validate` takes a positional `<PATH>`**, not `--lbr`.