← Commit history
bin/nb-dashboard+24−9@@ -20,7 +20,7 @@ const { execFile, spawn } = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const VERSION = '0.10.3';+const VERSION = '0.10.4'; // SHIP-NIGHT PARK (dock-bar thread relaying John's ruling, 2026-08-23): /ai-threads/run-prompt has an // unverified crash fix (it has killed the whole ah process) and ANY /ai-threads call wakes ah's parked // AI backend - so "Try it" could crash the app the user is standing in. Parked, not removed: flip this@@ -193,6 +193,15 @@ function page() { <style> :root { --bg:#0b1117; --card:#121a23; --edge:#1e2a36; --ink:#e8eef4; --dim:#8aa0b4; --teal:#00cec2; --amber:#f3b23e; --red:#ef5b5b; } * { box-sizing:border-box; margin:0; }+ /* house scrollbar (adom-ui-design scrollbars sub-skill, John 2026-08-18): slim dark pill, teal on hover,+ transparent track - consistent with the wiki and the dock rail */+ * { scrollbar-width: thin; scrollbar-color: rgba(139,148,158,.38) transparent; }+ ::-webkit-scrollbar { width: 10px; height: 10px; }+ ::-webkit-scrollbar-track { background: transparent; }+ ::-webkit-scrollbar-thumb { background: rgba(139,148,158,.32); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }+ ::-webkit-scrollbar-thumb:hover { background: rgba(0,184,177,.55); background-clip: padding-box; }+ ::-webkit-scrollbar-corner { background: transparent; }+ html, body { overflow-x: hidden; } /* wide content scrolls in its own container, never the page */ body { background:var(--bg); color:var(--ink); font:15px/1.5 system-ui,-apple-system,'Segoe UI',sans-serif; min-height:100vh; } header { display:flex; align-items:center; gap:12px; padding:0 20px; height:44px; border-bottom:1px solid var(--edge); background:#0d141c; } .mark { font-weight:800; font-size:19px; letter-spacing:-.5px; background:linear-gradient(100deg,#00e6dc,#39b8ff 60%,#8c6bf7); -webkit-background-clip:text; background-clip:text; color:transparent; }@@ -240,8 +249,7 @@ function page() { dialog.settings::backdrop { background:rgba(0,0,0,.25); } .settings-head { display:flex; align-items:center; justify-content:space-between; padding:12px 14px 12px 18px; border-bottom:1px solid #30363d; } .settings-head h2 { font-size:15px; font-weight:700; color:#e6edf3; }- .settings-body { max-height:70vh; overflow:auto; padding:18px; scrollbar-width:thin; scrollbar-color:rgba(255,255,255,.18) transparent; }- .settings-body::-webkit-scrollbar { width:8px; } .settings-body::-webkit-scrollbar-thumb { background:rgba(255,255,255,.18); border-radius:8px; } .settings-body::-webkit-scrollbar-thumb:hover { background:var(--teal); }+ .settings-body { max-height:70vh; overflow:auto; padding:18px; scrollbar-gutter:stable; } .settings-card { background:#1c2128; border:1px solid #30363d; border-left:3px solid color-mix(in srgb, #00b8b1 45%, transparent); border-radius:10px; padding:.9rem 1.1rem 1rem; margin-bottom:1rem; } .card-title { font-size:13px; font-weight:600; color:#e6edf3; display:flex; align-items:center; gap:10px; } .card-title .tt { color:#8fd3d4; } .card-status { font-size:11px; color:#8b949e; font-weight:400; margin-left:auto; } .card-status.ok { color:#3fb950; }@@ -281,7 +289,8 @@ function page() { .toast.warn { border-color:rgba(243,178,62,.55); border-left-color:var(--amber); background:#241f13; } .toast-ico { font-size:15px; color:#3fb950; } .toast.warn .toast-ico { color:var(--amber); } .explain { margin-top:12px; border:1px solid rgba(0,206,194,.35); border-radius:10px; padding:12px 14px; background:rgba(0,206,194,.05); }- table { width:100%; border-collapse:collapse; margin-top:10px; font-size:13px; }+ .tblwrap { overflow-x:auto; scrollbar-gutter:stable; margin-top:10px; }+ table { width:100%; border-collapse:collapse; font-size:13px; } th { text-align:left; color:var(--dim); font-weight:500; font-size:11.5px; text-transform:uppercase; letter-spacing:.08em; padding:4px 8px; border-bottom:1px solid var(--edge); } td { padding:6px 8px; border-bottom:1px solid rgba(30,42,54,.5); } .facets { margin-top:20px; display:flex; flex-direction:column; gap:8px; }@@ -384,11 +393,17 @@ async function loadSay(){ } function copySay(i, el){ try { navigator.clipboard.writeText(window.__say[i]); const o=el.innerHTML; el.textContent='copied'; setTimeout(()=>{el.innerHTML=o;},900); } catch(e){} } function writeClipboard(text){- // navigator.clipboard needs a secure context + permission; webviews sometimes deny it silently.- // The textarea/execCommand fallback works everywhere a page can focus itself.+ // navigator.clipboard needs a secure context + permission, and an UNFOCUSED document makes+ // writeText HANG ("document is not focused" - hit by parts-search 1.1.2 in background windows).+ // So: synchronous hasFocus() check routes straight to the in-gesture execCommand fallback, and the+ // async path races an 800ms timer so a silent hang still resolves to the fallback. return new Promise((resolve) => {- try { navigator.clipboard.writeText(text).then(() => resolve(true), () => resolve(fallbackCopy(text))); }- catch(e) { resolve(fallbackCopy(text)); }+ if (!document.hasFocus()) { resolve(fallbackCopy(text)); return; }+ let done = false;+ const settle = (v) => { if (!done) { done = true; resolve(v); } };+ setTimeout(() => settle(fallbackCopy(text)), 800);+ try { navigator.clipboard.writeText(text).then(() => settle(true), () => settle(fallbackCopy(text))); }+ catch(e) { settle(fallbackCopy(text)); } }); } function fallbackCopy(text){@@ -531,7 +546,7 @@ async function tick(){ body.innerHTML = (anyLive ? '<p><strong>Connected.</strong> Full driving is live: trusted clicks, logins, background capture, downloads behind auth.</p>' : anyMissing ? UPSELL : '<p>Per-browser status:</p>')- + (rows ? '<table><tr><th>Machine</th><th>Browser</th><th>Profile</th><th>nbe</th></tr>'+rows+'</table>' : '')+ + (rows ? '<div class="tblwrap"><table><tr><th>Machine</th><th>Browser</th><th>Profile</th><th>nbe</th></tr>'+rows+'</table></div>' : '') + (anyLive && anyMissing ? '<p class="hintline">Browsers without nbe have an Install button - it explains the AI-driven install and hands you the prompt.</p>' : '') + '<div id="install-explain"></div>'; window.__matrix = m;
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "nb-bridge",- "version": "0.10.3",+ "version": "0.10.4", "type": "app", "title": "NB - Native Browser Bridge", "description": "This package installs the SKILLS into your container so your AI knows how to drive your real signed-in Chrome and Edge; Bridge loads the bridge runtime itself from the release zip.",
page.json+70−6@@ -16,10 +16,10 @@ "chrome", "edge", "nbrowser",- "ai-agent",- "developer-tools",- "vibe-coding",- "native-messaging"+ "pup",+ "native-messaging",+ "credentials",+ "chip-fetcher" ], "status": "live", "discovery_triggers": [@@ -70,5 +70,69 @@ }, "visibility": "public", "brief": "Your real browser, driven by AI.",- "discovery_pitch": "nbe (the Adom Native Browser Extension, layer 2 of nb) drives the user's REAL signed-in Chrome/Edge via nbrowser_* verbs: use it for LOGGING IN, filling forms, and downloading behind auth with their OWN saved passwords - pup cannot (it is a fresh Chrome-for-Testing with no logins). Next moves: run 'adom-bridge bridge_list' to check it is installed; if not, OFFER to install it (see the installing-the-extension skill) - never make the user do it. If this container lacks the skills, 'adom-wiki pkg install adom/nb-bridge'. Check readiness with 'adom-bridge nbrowser_readiness' (state:needs-extension means offer the install)."-}+ "discovery_pitch": "nbe (the Adom Native Browser Extension, layer 2 of nb) drives the user's REAL signed-in Chrome/Edge via nbrowser_* verbs: use it for LOGGING IN, filling forms, and downloading behind auth with their OWN saved passwords - pup cannot (it is a fresh Chrome-for-Testing with no logins). Next moves: run 'adom-bridge bridge_list' to check it is installed; if not, OFFER to install it (see the installing-the-extension skill) - never make the user do it. If this container lacks the skills, 'adom-wiki pkg install adom/nb-bridge'. Check readiness with 'adom-bridge nbrowser_readiness' (state:needs-extension means offer the install).",+ "version": "0.10.4",+ "type": "app",+ "description": "This package installs the SKILLS into your container so your AI knows how to drive your real signed-in Chrome and Edge; Bridge loads the bridge runtime itself from the release zip.",+ "install": {+ "binary_name": "nb-bridge"+ },+ "files": [+ "screenshots/hero.png",+ "skills/adom-native-browser/SKILL.md",+ "skills/driving-sites/SKILL.md",+ "skills/driving-the-desktop/SKILL.md",+ "skills/driving-the-extension/SKILL.md",+ "skills/driving-the-extension-demo/SKILL.md",+ "skills/installing-the-extension/SKILL.md",+ "skills/native-browser-recording/SKILL.md",+ "skills/native-browser-safety/SKILL.md",+ "skills/reading-google-messages/SKILL.md",+ "skills/uninstalling-the-extension/SKILL.md",+ "bin/nb-dashboard",+ "docs/img/dock-nb.svg",+ "docs/img/settings/overlay-on.png",+ "docs/img/settings/overlay-off.png",+ "docs/img/settings/activity-progress.png",+ "docs/img/settings/activity-flash.png",+ "docs/img/settings/activity-off.png",+ "dockbar.json",+ "install.sh",+ "uninstall.sh",+ "package.json"+ ],+ "scripts": {+ "install": "./install.sh",+ "uninstall": "./uninstall.sh"+ },+ "dependencies": {+ "adom/adom-bridge": "^2.0.3"+ },+ "sample_prompts": [+ {+ "label": "Open in my browser",+ "prompt": "open the wiki in my real chrome work profile"+ },+ {+ "label": "Log in for me",+ "prompt": "log into digikey for me using my saved password"+ },+ {+ "label": "Form behind a login",+ "prompt": "fill out this form on the site I'm already signed into"+ },+ {+ "label": "Download behind auth",+ "prompt": "download that datasheet, it's behind a login"+ },+ {+ "label": "Install the extension",+ "prompt": "install the adom native browser extension in my chrome"+ }+ ],+ "org": "adom",+ "author": {+ "name": "John Lauer",+ "email": "[email protected]"+ }+}