← Commit history

Publish 0.9.1

John Lauer ·779e5aab9b ·2mo ago ·parent c6aaf1a
3 files changed +95−15
bin/nb-dashboard+29−8
@@ -20,7 +20,7 @@ const { execFile, spawn } = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const VERSION = '0.9.0';           // keep in lockstep with package.json (pkg version)+const VERSION = '0.9.1';           // keep in lockstep with package.json (pkg version) const path = require('path'); // TEACH THE NOUN (John, 2026-08-23): "I say 'open digikey in nb' cuz for that I might know I need nb // since it has my login. Or 'open mouser in nb chrome personal'..." The phrases users should SAY,@@ -62,14 +62,35 @@ function httpJson(method, url, body) {   }); } async function tryPhrase(prompt) {+  // Lookup order measured against the live control API (dock-bar thread, 2026-08-23):+  //   1. CENSUS  GET /ai-threads -> {ok, groups:[{threads:[{tid, type, label, sid|null, tags:[]}]}]}+  //      (rows live at groups[].threads[]; sid is null for a fresh staged thread -> address by tid)+  //   2. HISTORY GET /ai-threads/history?tag=... -> {ok, items:[{ai, id, title, updated_ms}], open_excluded}+  //      (closed threads only; POST /ai-threads/resume {ai,id} reopens, then run-prompt {sid:id})+  //   3. neither -> honest copy fallback (the page copies the phrase and says why)   const base = controlUrl();-  const list = await httpJson('GET', base + '/ai-threads');-  const arr = (list.json && (Array.isArray(list.json) ? list.json : (list.json.threads || list.json.items || list.json.data))) || [];-  const mine = arr.find((t) => JSON.stringify(t.tags || t.tag || '').includes('app:adom/nb-bridge'));-  const sid = mine && (mine.sid || mine.id || mine.session_id);-  if (!sid) return { ok: false, staged: false, reason: list.status ? 'no thread tagged app:adom/nb-bridge yet (open nb from the dock once)' : ('control API unreachable at ' + base), control: base };-  const r = await httpJson('POST', base + '/ai-threads/run-prompt', { sid, prompt, submit: false });-  return { ok: r.status >= 200 && r.status < 300, staged: r.status >= 200 && r.status < 300, sid, status: r.status, detail: r.text || r.error, control: base };+  const TAG = 'app:adom/nb-bridge';+  const census = await httpJson('GET', base + '/ai-threads');+  if (!census.status) return { ok: false, staged: false, reason: 'control API unreachable at ' + base, control: base };+  const rows = [];+  for (const g of ((census.json && census.json.groups) || [])) for (const t of (g.threads || [])) rows.push(t);+  const open = rows.find((t) => Array.isArray(t.tags) && t.tags.includes(TAG));+  if (open) {+    const addr = open.sid ? { sid: open.sid } : { tid: open.tid };+    const r = await httpJson('POST', base + '/ai-threads/run-prompt', { ...addr, prompt, submit: false });+    return { ok: r.status >= 200 && r.status < 300, staged: r.status >= 200 && r.status < 300, via: 'census', ...addr, status: r.status, detail: r.text || r.error, control: base };+  }+  const hist = await httpJson('GET', base + '/ai-threads/history?tag=' + encodeURIComponent(TAG));+  const item = ((hist.json && hist.json.items) || [])[0];+  if (item && item.id) {+    const re = await httpJson('POST', base + '/ai-threads/resume', { ai: item.ai, id: item.id });+    if (re.status >= 200 && re.status < 300) {+      const r = await httpJson('POST', base + '/ai-threads/run-prompt', { sid: item.id, prompt, submit: false });+      return { ok: r.status >= 200 && r.status < 300, staged: r.status >= 200 && r.status < 300, via: 'history-resumed', sid: item.id, status: r.status, detail: r.text || r.error, control: base };+    }+    return { ok: false, staged: false, reason: 'nb thread exists in history but could not be resumed (status ' + re.status + ')', control: base };+  }+  return { ok: false, staged: false, reason: 'no nb AI thread yet - open nb from the dock once, then Try it stages into it', control: base }; } // 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
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "nb-bridge",-  "version": "0.9.0",+  "version": "0.9.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+65−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,64 @@   },   "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.9.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",+    "docs/img/dock-nb.svg",+    "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