← Commit history

Publish 0.8.1

John Lauer ·655263d294 ·2mo ago ·parent d52f8ca
3 files changed +85−13
bin/nb-dashboard+20−6
@@ -17,8 +17,14 @@ 'use strict'; const http = require('http'); const { execFile, spawn } = require('child_process');+const fs = require('fs');+const crypto = require('crypto'); -const VERSION = '0.8.0';           // keep in lockstep with package.json (pkg version)+const VERSION = '0.8.1';           // keep in lockstep with package.json (pkg version)+// BUILD = hash of this very file. Version-aware reuse compared the VERSION string alone and happily+// kept serving a stale process whose code had changed under the same version (2026-08-23) - the+// dock guide's version-blind trap at one finer grain. Reuse now requires version AND build to match.+const BUILD = (() => { try { return crypto.createHash('sha1').update(fs.readFileSync(__filename)).digest('hex').slice(0, 10); } catch { return 'unknown'; } })(); const PORT = 8954; const URL_SELF = `http://127.0.0.1:${PORT}/`; @@ -183,6 +189,7 @@ const UPSELL = '<p><strong>Not installed yet</strong> - and it is the single bes   + '<div class="prompt"><code id="pr">install the adom native browser extension in my chrome</code><button onclick="copyPrompt()">Copy</button></div>'   + '<p class="hintline">Paste that into any Adom AI thread to start.</p>'; function copyPrompt(){ try { navigator.clipboard.writeText(document.getElementById('pr').textContent); } catch(e){} }+function copyPrompt2(btn){ try { navigator.clipboard.writeText(document.getElementById('pr2').textContent); btn.textContent = 'Copied!'; } catch(e){} } function installPrompt(i){   const r = (window.__matrix||[])[i]; if (!r) return;   const p = 'install the adom native browser extension in my ' + r.browser + ' on ' + r.machine;@@ -195,7 +202,7 @@ function installPrompt(i){     + 'connection. Takes about a minute; you approve one folder picker.</p>'     + '<p>Paste this to any Adom AI thread:</p>'     + '<div class="prompt"><code id="pr2">' + p + '</code>'-    + '<button onclick="try{navigator.clipboard.writeText(document.getElementById(\'pr2\').textContent);this.textContent=\'Copied!\';}catch(e){}">Copy</button></div>'+    + '<button onclick="copyPrompt2(this)">Copy</button></div>'     + '</div>';   box.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }@@ -256,7 +263,7 @@ function startServer() {     const u = String(req.url || '/');     if (u.startsWith('/api/status')) {       res.writeHead(200, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });-      res.end(JSON.stringify({ state: cache.state, version: VERSION, facets: cache.facets, targets: cache.targets, matrix: cache.matrix || [], cacheAgeMs: Date.now() - cache.at }));+      res.end(JSON.stringify({ state: cache.state, version: VERSION, build: BUILD, facets: cache.facets, targets: cache.targets, matrix: cache.matrix || [], cacheAgeMs: Date.now() - cache.at }));       return;     }     if (u.startsWith('/api/shutdown') && req.method === 'POST') {@@ -292,7 +299,7 @@ function probeExisting() {  async function serve(printUrl) {   const existing = await probeExisting();-  if (existing && existing.version === VERSION) {+  if (existing && existing.version === VERSION && existing.build === BUILD) {     if (printUrl) process.stdout.write(URL_SELF + '\n');     process.exit(0);   }@@ -311,7 +318,7 @@ async function serve(printUrl) {   for (let i = 0; i < 40; i++) {     await new Promise((r) => setTimeout(r, 250));     const up = await probeExisting();-    if (up && up.version === VERSION) { if (printUrl) process.stdout.write(URL_SELF + '\n'); process.exit(0); }+    if (up && up.version === VERSION && up.build === BUILD) { if (printUrl) process.stdout.write(URL_SELF + '\n'); process.exit(0); }   }   process.stderr.write('nb-dashboard: server did not come up\n');   process.exit(1);@@ -324,5 +331,12 @@ else if (cmd === 'status') probeExisting().then((d) => { console.log(JSON.string else if (cmd === 'stop') {   const req = http.request({ host: '127.0.0.1', port: PORT, path: '/api/shutdown', method: 'POST' }, () => { console.log('stopped'); process.exit(0); });   req.on('error', () => { console.log('not running'); process.exit(0); }); req.end();-} else if (cmd === '--version' || cmd === 'version') { console.log(VERSION); process.exit(0); }+} else if (cmd === 'selfcheck') {+  // Ship gate: the page's inline script must PARSE (a quoting slip once shipped a blank dashboard).+  const vm = require('vm');+  const m = /<script>([\s\S]*?)<\/script>/.exec(page());+  try { new vm.Script(m ? m[1] : ''); console.log('selfcheck ok: inline script parses; build ' + BUILD); process.exit(0); }+  catch (e) { console.error('selfcheck FAILED: inline script does not parse: ' + e.message); process.exit(1); }+}+else if (cmd === '--version' || cmd === 'version') { console.log(VERSION); process.exit(0); } else { console.log('usage: nb-dashboard serve [--print-url] | status | stop | version'); process.exit(1); }
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "nb-bridge",-  "version": "0.8.0",+  "version": "0.8.1",   "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+64−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,63 @@   },   "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.8.1",+  "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",+    "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