← Commit history

Publish 0.10.3

John Lauer ·d3f3db506e ·2mo ago ·parent b9a7ad9
3 files changed +109−18
bin/nb-dashboard+38−11
@@ -20,7 +20,7 @@ const { execFile, spawn } = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const VERSION = '0.10.2';+const VERSION = '0.10.3'; // 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@@ -274,6 +274,12 @@ function page() {   .footer-note { font-size:.75rem; color:#8b949e; } .footer-note code { font-size:11px; }   .restore-btn { width:fit-content; padding:.4rem .85rem; background:transparent; border:1px solid #30363d; border-radius:.375rem; color:#c9d1d9; font-size:.8125rem; font-weight:600; cursor:pointer; }   .restore-btn:hover { background:#1c2128; } .restore-btn.armed { color:#f85149; border-color:rgba(255,107,107,.5); background:rgba(255,107,107,.08); }+  .toast { position:fixed; left:50%; bottom:28px; transform:translate(-50%, 16px); display:flex; align-items:center; gap:10px;+    background:#132420; color:#e8eef4; border:1px solid rgba(63,185,80,.55); border-left:3px solid #3fb950; border-radius:10px;+    padding:10px 16px; font-size:13.5px; opacity:0; pointer-events:none; transition:opacity .18s ease, transform .18s ease; z-index:50; max-width:90vw; }+  .toast.show { opacity:1; transform:translate(-50%, 0); }+  .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; }   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); }@@ -372,21 +378,42 @@ async function loadSay(){   try {     const r = await fetch('api/say'); const d = await r.json();     document.getElementById('say-row').innerHTML = (d.say||[]).map((p,i)=>-      '<span class="chip"><span class="ph" title="click to copy" onclick="copySay('+i+',this)">'+hiNoun(p)+'</span>'+(d.tryit?'<button class="try" onclick="trySay('+i+',this)">Try it</button>':'')+'</span>').join('');+      '<span class="chip"><span class="ph" title="click to copy" onclick="copySay('+i+',this)">'+hiNoun(p)+'</span><button class="try" onclick="trySay('+i+',this)">Try it</button></span>').join('');     window.__say = d.say || [];   } catch(e){} } 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){} }-async function trySay(i, btn){-  const phrase = window.__say[i]; const note = document.getElementById('say-note');-  btn.textContent = '...';+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.+  return new Promise((resolve) => {+    try { navigator.clipboard.writeText(text).then(() => resolve(true), () => resolve(fallbackCopy(text))); }+    catch(e) { resolve(fallbackCopy(text)); }+  });+}+function fallbackCopy(text){   try {-    const r = await fetch('api/try', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ phrase }) });-    const d = await r.json();-    if (d.staged) { btn.textContent = 'Staged'; note.innerHTML = 'Staged <em>"'+phrase+'"</em> into your nb AI thread, unsent - review it and press enter.'; }-    else { try { navigator.clipboard.writeText(phrase); } catch(e){} btn.textContent = 'Copied'; note.innerHTML = 'Copied <em>"'+phrase+'"</em>. Could not stage it into a thread ('+(d.reason||('status '+d.status))+'), so paste it to your AI.'; }-  } catch(e) { btn.textContent = 'Try it'; }-  setTimeout(()=>{ btn.textContent='Try it'; }, 2500);+    const ta = document.createElement('textarea');+    ta.value = text; ta.setAttribute('readonly',''); ta.style.position='fixed'; ta.style.left='-9999px';+    document.body.appendChild(ta); ta.select(); const ok = document.execCommand('copy'); ta.remove(); return ok;+  } catch(e){ return false; }+}+let _toastT = null;+function toast(msg, ok){+  let t = document.getElementById('toast');+  if (!t) { t = document.createElement('div'); t.id='toast'; document.body.appendChild(t); }+  t.className = 'toast ' + (ok ? 'ok' : 'warn');+  t.innerHTML = '<span class="toast-ico">' + (ok ? '&#10003;' : '&#9888;') + '</span>' + msg;+  t.classList.add('show');+  clearTimeout(_toastT); _toastT = setTimeout(() => t.classList.remove('show'), 4000);+}+async function trySay(i, btn){+  // SHIP UX (John, 2026-08-23): Try it copies the prompt and SAYS SO - no AI-thread calls of any kind+  // (that path is parked server-side too; the staging code sleeps behind TRYIT_PARKED).+  const phrase = window.__say[i];+  const ok = await writeClipboard(phrase);+  if (ok) toast('Copied to clipboard. Paste it into any AI thread.', true);+  else toast('Could not copy automatically - select the phrase and copy it yourself.', false); } loadSay(); // ---- settings modal ----
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "nb-bridge",-  "version": "0.10.2",+  "version": "0.10.3",   "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.3",+  "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]"+  }+}\ No newline at end of file