← Commit history

dashboard 1.9.61: open verb; skill + changelog

John Lauer ·a09015933f ·1mo ago ·parent d001534
8 files changed +66−11
CHANGELOG.md+4
@@ -11,6 +11,10 @@ Canonical: https://wiki.adom.inc/adom/fusion-bridge ยท GitHub backup: `adom-inc/ - **Zombie-window gate on the save-prompt sentinel**: an UNATTRIBUTED "Save" dialog is only   escalated (Escape) when the add-in main thread is actually blocked; responsive-thread ghosts   (ConfRoomROG's black no-UIA windows) are left alone instead of escape-spammed every sweep.+- **`fusion-dashboard open [--pup|--webview]` shipped** - the founding contract's third CLI verb:+  --pup opens the Dashboard in a BACKGROUND pup window on the user's desktop (taskbar flash, never+  foregrounded); --webview prints the URL + the webview-skill instruction (panel placement is the+  AI's call, never a CLI guess). Auto-discovers the serving port and the proxy URL. - **Graceful stop hardening**: the clean-close document pass retries once (3s + 10s budget)   instead of silently skipping on a transiently-busy add-in - skipping was what let WM_CLOSE hit   the unsaved-doc Save modal. On failure, `bridgeDocsOnly:true` + a kill-is-safe hint when every
bin/fusion-dashboard
⋯ 1 unchanged line ⋯
dashboard/Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "fusion-dashboard"-version = "1.9.60"+version = "1.9.61" edition = "2021"  [dependencies]
dashboard/src/main.rs+44
@@ -512,6 +512,49 @@ fn main() {                 }             }         }+        "open" => {+            // The founding contract's third verb: put the Dashboard on a surface. --pup (default)+            // opens a BACKGROUND pup window on the user's desktop via ab (never steals focus);+            // --webview prints the URL + the exact instruction for the AI, because Hydrogen+            // panel-id resolution is the webview skill's job, not a CLI guess.+            let mut port = 0u16;+            for p in 8930..=8940u16 {+                if let Ok(o) = Command::new("curl").args(["-s", "-m", "2", &format!("http://127.0.0.1:{}/health", p)]).output() {+                    if o.status.success() && String::from_utf8_lossy(&o.stdout).contains("\"ok\":true") { port = p; break; }+                }+            }+            if port == 0 {+                err_hint("no fusion-dashboard server is running", "Start it first: `fusion-dashboard serve &`, then re-run open.");+                std::process::exit(1);+            }+            let url = match std::env::var("VSCODE_PROXY_URI") {+                Ok(t) if t.contains("{{port}}") => t.replace("{{port}}", &port.to_string()),+                _ => format!("http://127.0.0.1:{}/", port),+            };+            let webview = args.iter().any(|a| a == "--webview");+            if webview {+                ok(&format!("Dashboard is serving at {}", url));+                println!("Hint: to place it in a Hydrogen webview tab, load the `webview` skill (adom-workspace-control) and add a tab for that URL - panel selection is the AI's call, never this CLI's.");+            } else {+                let target = get_flag("--target");+                let mut cmd = Command::new("adom-bridge");+                if let Some(t) = &target { cmd.args(["--target", t]); }+                cmd.args(["--ai-thread", &ai_thread, "pup_open_window",+                          &serde_json::json!({"url": url, "background": true}).to_string()]);+                match cmd.output() {+                    Ok(o) => {+                        let out = String::from_utf8_lossy(&o.stdout);+                        if out.contains("\"status\": \"ok\"") || out.contains("\"status\":\"ok\"") {+                            ok(&format!("Dashboard opened in a BACKGROUND pup window at {} (taskbar flashes; the user brings it up when ready - never foregrounded)", url));+                        } else {+                            err_hint(&format!("pup_open_window did not confirm: {}", out.chars().take(200).collect::<String>()),+                                     "Is a desktop connected? `adom-bridge targets`. The URL above still works in any browser.");+                        }+                    }+                    Err(e) => err_hint(&format!("adom-bridge not runnable: {}", e), "The container ships adom-bridge on PATH."),+                }+            }+        }         "health" => ok(&format!("fusion-dashboard v{}", VERSION)),         _ => {             println!("fusion-dashboard v{} - the fusion bridge's Launch Page", VERSION);@@ -520,6 +563,7 @@ fn main() {             println!("  ui toast \"msg\" [--kind ok|err|info] [--port]            narrate a toast over the running app");             println!("  ui click <setup|start|stop|tour|import-part|settings|refresh>   drive the real UI");             println!("  ui state | ui console                                   observe the running app");+            println!("  open [--pup (default) | --webview] [--target <box>]     put the Dashboard on a surface (pup = background window)");             println!("  health                                                  liveness");             println!("  (global: --ai-thread <name> attributes bridge calls in the Activity Log)");             println!("Hint: `fusion-dashboard serve --print-url` is the Hydrogen dock launch step.");
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.9.60"+DASH_VERSION="1.9.61" 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.9.60",+  "version": "1.9.61",   "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−8
@@ -1,16 +1,20 @@ {   "slug": "fusion-bridge",-  "version": "1.9.60",+  "version": "1.9.61",   "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": {-    "adom/adom-desktop": "*"+    "adom/adom-desktop": "^1.9.0"   },   "scripts": {     "install": "./install.sh",     "uninstall": "./uninstall.sh"   },   "tags": [+    "ab",+    "bridge",+    "fusion",+    "desktop-app",     "fusion360",     "autodesk",     "cad",@@ -70,7 +74,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.",@@ -99,9 +106,5 @@       "label": "Part volume",       "prompt": "How much material does each printed part in this assembly use?"     }-  ],-  "author": {-    "name": "John Lauer",-    "email": "[email protected]"-  }+  ] }\ No newline at end of file
skills/fusion-dashboard/SKILL.md+4
@@ -19,10 +19,14 @@ fusion-dashboard status [--target <box>]                              # one-shot fusion-dashboard ui toast "msg" [--kind ok|err|info]                  # narrate OVER the running app fusion-dashboard ui click <setup|start|stop|tour|import-part|settings|refresh> fusion-dashboard ui state | ui console                                # observe the running app+fusion-dashboard open [--pup (default) | --webview] [--target <box>]  # put it on a surface fusion-dashboard health                                               # liveness ```  - `serve --print-url` prints the local URL first - the Hydrogen dock's `await:"url"` step.+- `open --pup` opens a BACKGROUND pup window on the user's desktop (taskbar flashes; never+  steals focus). `open --webview` prints the proxy URL plus the webview-skill instruction -+  panel placement stays the AI's decision. - No `--target` = first box from `adom-bridge targets`. Global `--ai-thread <name>`   attributes every bridge call in the user's Activity Log. - HTTP: `GET /api/status` (the LED payload), `POST /api/action {action, args}` (start,