← Commit history

Publish 0.12.1

John Lauer ·34a6bff289 ·2mo ago ·parent 0939bcb
3 files changed +102−16
bin/nb-dashboard+26−9
@@ -20,7 +20,7 @@ const { execFile, spawn } = require('child_process'); const fs = require('fs'); const crypto = require('crypto'); -const VERSION = '0.12.0';           // keep in lockstep with package.json (pkg version)+const VERSION = '0.12.1';           // keep in lockstep with package.json (pkg version) // SEND TO AI IS UN-PARKED (John: "yeah, we are re-enabling the send to ai. it seems to be good now"). // The ah build thread certified the crash family dead on the gate-fixed build and the delivery leg is // proven end to end. The park const is DELETED rather than flipped, so no dead branch can resurrect it.@@ -72,12 +72,12 @@ function controlUrl() {   try { const u = fs.readFileSync(path.join(require('os').homedir(), '.adom', 'hydrogen-control-url'), 'utf8').trim(); if (u) return u.replace(/\/$/, ''); } catch {}   return 'http://127.0.0.1:47084'; }-function httpJson(method, url, body) {+function httpJson(method, url, body, timeoutMs) {   return new Promise((resolve) => {     try {       const u = new URL(url);       const data = body ? JSON.stringify(body) : null;-      const req = http.request({ host: u.hostname, port: u.port, path: u.pathname + u.search, method, timeout: 5000,+      const req = http.request({ host: u.hostname, port: u.port, path: u.pathname + u.search, method, timeout: timeoutMs || 5000,         headers: data ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) } : {} }, (res) => {         let b = ''; res.on('data', (c) => (b += c)); res.on('end', () => { let j = null; try { j = JSON.parse(b); } catch {} resolve({ status: res.statusCode, json: j, text: b.slice(0, 300) }); });       });@@ -87,16 +87,33 @@ function httpJson(method, url, body) {   }); } async function saySend(phrase) {+  // ONE CALL composite. NOT the two-step new-then-send-by-sid flow: /ai-threads/new has NEVER+  // returned an id (a thread has no sid until its first submitted prompt), so a client that reads+  // sid||id from /new always aborts and ships a Send button that opens a tab and delivers nothing.+  // I shipped exactly that in 0.12.0 and it was caught in review before John pressed it.+  // `new:true` inside run-prompt creates the thread; name and tags stage on the SAME request.   const base = controlUrl();   const gate = await shellVersionOk();   if (!gate.ok) return { ok: false, why: `your Hydrogen is ${gate.version} and Send to AI needs 1.0.142 or newer (1.0.141 carries a crash this would trigger) - update Hydrogen to enable it; the phrase is on your clipboard` };   try {-    const mk = await httpJson('POST', base + '/ai-threads/new', { name: 'Native Browser - say it', tags: ['dock:nb-bridge'] });-    const sid = mk.json && (mk.json.sid || mk.json.id);-    if (!(mk.status >= 200 && mk.status < 300) || !sid) return { ok: false, why: mk.status ? ('could not create a thread (status ' + mk.status + ')') : ('AI panel unreachable at ' + base) };-    const run = await httpJson('POST', base + '/ai-threads/run-prompt', { sid, prompt: phrase, submit: true });-    if (run.status >= 200 && run.status < 300) return { ok: true, sid };-    return { ok: false, why: 'thread created but the prompt did not send (status ' + run.status + '); the staged thread expires on its own', sid };+    // 120s: the tab CREATE alone can take 60s on a loaded workbench, and a short client timeout+    // turns a working send into a spurious "could not reach the AI panel".+    const r = await httpJson('POST', base + '/ai-threads/run-prompt', {+      new: true, prompt: phrase, submit: true,+      name: 'NB - say it', tags: ['dock:nb-bridge'],+    }, 120000);+    if (!(r.status >= 200 && r.status < 300)) {+      const hint = r.json && (r.json._hints ? (typeof r.json._hints === 'string' ? r.json._hints : JSON.stringify(r.json._hints)) : r.json.error);+      return { ok: false, why: hint || (r.status ? `the AI panel refused the prompt (status ${r.status})` : `AI panel unreachable at ${base}`) };+    }+    // Delivery is proven by delivered_to, NEVER by the thread's name: a perfectly named tab with a+    // null delivered_to means nothing was typed, and an unnamed tab with a truthy one succeeded.+    const delivered = r.json && r.json.delivered_to;+    if (!delivered) {+      const hint = r.json && r.json._hints ? (typeof r.json._hints === 'string' ? r.json._hints : JSON.stringify(r.json._hints)) : null;+      return { ok: false, why: hint || 'the AI panel opened a thread but did not confirm delivery - do not resend, the tab may still be settling' };+    }+    return { ok: true, delivered_to: delivered };   } catch (e) { return { ok: false, why: String(e && e.message || e) }; } } // ---- the guided demo (dash-demo contract) ----------------------------------
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "nb-bridge",-  "version": "0.12.0",+  "version": "0.12.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+75−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,74 @@   },   "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.12.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",+    "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",+    "demo/audio/intro.mp3",+    "demo/audio/open.mp3",+    "demo/audio/shot.mp3",+    "demo/audio/click.mp3",+    "demo/audio/wrap.mp3",+    "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