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
Publish 1.9.214
3 files changed
+80−12
addin/AdomBridge/commands/close_document.py+43−2@@ -89,6 +89,11 @@ def handle_close_document(app: adsk.core.Application, args: dict) -> dict: def handle_close_all_documents(app: adsk.core.Application, args: dict) -> dict: """Close ALL open documents without save dialogs. + ⛔ One case genuinely cannot be closed silently and is REFUSED rather than prompted:+ a document with a NAME but no dataFile (never saved) that is MODIFIED. Fusion has no+ location to write it to, so close() raises the Save box even with saveChanges=False.+ Such docs are returned in data.wouldPrompt with errorCode unsaved_named_document.+ Closes every open document/tab in Fusion without triggering any save dialogs. Essential before restarting Fusion to avoid the 'Recovered Documents' modal on next launch.@@ -107,6 +112,7 @@ def handle_close_all_documents(app: adsk.core.Application, args: dict) -> dict: closed = [] errors = [] skipped = []+ would_prompt = [] # Snapshot the current document list ONCE. Do NOT loop on app.documents.count, # because Fusion may auto-create an Untitled blank doc whenever all docs close,@@ -156,21 +162,56 @@ def handle_close_all_documents(app: adsk.core.Application, args: dict) -> dict: if is_modified and not force_untitled: skipped.append(doc_name + " (modified - pass force:true to discard)") continue+ # ⛔ A NAMED-BUT-NEVER-SAVED MODIFIED DOC MAKES close() PROMPT.+ # John, 2026-08-26: "why do i ever see this dialog popup if you are pre-emptively+ # saving programmatically?" He was looking at Fusion's Save box (Name: TJA1042T,+ # Location: Admin Project) raised by THIS function, whose docstring promises+ # "without save dialogs". doc.close(False) discards silently for a scratch+ # Untitled, but a doc that has a NAME and no dataFile has never been saved, so+ # Fusion has nowhere to put it and asks - even when saveChanges is False.+ # Per skills/fusion-no-modal-dialogs: never issue a command that will prompt.+ # This case is knowable here, before the call, so decide it here.+ if (not has_data_file and doc_name and+ not doc_name.lower().startswith("untitled")):+ is_mod = False+ try:+ is_mod = bool(doc.isModified)+ except Exception:+ is_mod = False+ if is_mod and not save_changes:+ would_prompt.append(doc_name)+ continue doc.close(save_changes) closed.append(doc_name) except Exception as e: errors.append(f"{doc_name}: {e}") # Keep going — don't abort the whole batch on one failure - return {- "success": len(errors) == 0,+ result = {+ "success": len(errors) == 0 and not would_prompt, "output": f"Closed {len(closed)} document(s)" + (f", skipped {len(skipped)} Untitled" if skipped else "")+ + (f", REFUSED {len(would_prompt)} unsaved" if would_prompt else "") + (f", {len(errors)} error(s)" if errors else ""), "data": { "closed": closed, "skipped": skipped if skipped else None,+ "wouldPrompt": would_prompt if would_prompt else None, "errors": errors if errors else None, "remainingDocuments": app.documents.count, }, }+ if would_prompt:+ result["errorCode"] = "unsaved_named_document"+ result["error"] = (+ "Refused to close %s: never saved and modified, so Fusion would raise its Save "+ "box (it has no name/location to write to). NOTHING was closed for these and no "+ "dialog was raised." % ", ".join(repr(n) for n in would_prompt))+ result["_hint"] = (+ "Pick one, both are dialog-free: (a) save it first with an EXPLICIT destination "+ "- fusion_save_to_cloud {name, projectName, folderPath} - which never prompts "+ "because you supply what the dialog would ask for, then close; or (b) call this "+ "again with save:true, which saves through the same API path. Fusion's API "+ "cannot discard a named, never-saved document silently, so there is no third "+ "option that avoids the modal.")+ return result
page.json+7−10@@ -11,10 +11,6 @@ "uninstall": "./uninstall.sh" }, "tags": [- "ab",- "bridge",- "fusion",- "desktop-app", "fusion360", "autodesk", "cad",@@ -79,10 +75,7 @@ "build a basic parts library", "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"+ "set up the fusion bridge" ], "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.",@@ -111,5 +104,9 @@ "label": "Part volume", "prompt": "How much material does each printed part in this assembly use?" }- ]-}+ ],+ "author": {+ "name": "John Lauer",+ "email": "[email protected]"+ }+}
skills/fusion-no-modal-dialogs/SKILL.md+30@@ -127,6 +127,36 @@ bad = [e for e in edits if "TJA1042T.pac" in e] assert not bad, "EDIT was issued -> dialog would pop" ``` +## A verb's docstring is not evidence that it does not prompt++`fusion_close_all_documents` says "Close ALL open documents **without save dialogs**". Two+hours after writing this skill I called it to clear a workspace and it raised Fusion's Save+box (Name: TJA1042T, Location: Admin Project) at John. I trusted the sentence instead of the+behaviour - the same mistake this whole document is about, made on the very next action.++**The actual rule Fusion enforces:** `doc.close(False)` discards silently for a scratch+`Untitled`, but a document that has a **NAME and no dataFile has never been saved**, so+Fusion has nowhere to write it and asks - *even when saveChanges is False*. There is no API+to discard such a document silently.++Since it is knowable before the call (`dataFile is None` and `isModified` and the name is+not `Untitled*`), it gets decided before the call: those docs are **refused**, returned in+`data.wouldPrompt` with `errorCode: unsaved_named_document`, and `close()` is never invoked+on them. The caller then picks a dialog-free path - save with an explicit+`{name, projectName, folderPath}` (no prompt, because you supply exactly what the dialog+would ask for), or `save: true`.++**Generalise it:** when a verb claims it cannot prompt, that claim is a hypothesis. The test+is what reached Fusion and what appeared on screen, not what the docstring asserts.++## Closing a workspace before a restart, in order++1. Enumerate documents first (`fusion_get_app_state`) and look at `isSaved` per doc.+2. Scratch `Untitled` + unmodified: `closeUntitled: true` closes them silently.+3. Saved docs: close normally.+4. Named + never saved + modified: **save it with an explicit destination, then close.**+ Never call close and hope.+ ## Commands that prompt (assume prompting unless proven otherwise) | Command | Prompt | Prevention |