← Commit history

2.11.6: Try it returns as copy-with-toast; zero /ai-threads calls

John Lauer ·71f8f727de ·1mo ago ·parent 3052347
6 files changed +37−31
Cargo.lock+1−1
@@ -10,7 +10,7 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"  [[package]] name = "adom-lbr"-version = "2.11.5"+version = "2.11.6" dependencies = [  "altium-codec",  "anyhow",
Cargo.toml+1−1
@@ -1,6 +1,6 @@ [package] name = "adom-lbr"-version = "2.11.5"+version = "2.11.6" edition = "2021" description = "adom-lbr generator / EDA translator: the canonical adom-lbr JSON is the hub, with native converters to Altium (.SchLib/.PcbLib/.IntLib), EAGLE/Fusion (.lbr), and KiCad. Altium output is written natively — no Altium needed at conversion time." 
VERSION+1−1
@@ -1 +1 @@-2.11.5+2.11.6
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.11.5",+  "version": "2.11.6",   "type": "app",   "description": "adom-lbr \u2014 the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad \u21c4 Altium \u21c4 EAGLE/Fusion) through one canonical adom-lbr JSON \u2014 symbol + footprint + 3D + pin\u2194pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},
page.json+9−12
@@ -1,8 +1,8 @@ {   "slug": "adom-lbr",-  "version": "2.11.5",+  "version": "2.11.6",   "type": "app",-  "description": "adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",+  "description": "adom-lbr \u2014 the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad \u21c4 Altium \u21c4 EAGLE/Fusion) through one canonical adom-lbr JSON \u2014 symbol + footprint + 3D + pin\u2194pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},   "tags": [     "eda",@@ -52,24 +52,21 @@   ],   "files": [     "bin/**",-    "assets/**",     "SKILL.md",-    "skills/**",     "README.md",     "install.sh",     "uninstall.sh",-    "screenshots/**",-    "dockbar.json"+    "screenshots/**"   ],-  "discovery_pitch": "Convert electronic-component symbols + footprints between any two EDA tools — KiCad, Altium (written natively, no Altium needed), and EAGLE/Fusion — through one canonical adom-lbr JSON, silk/courtyard/fab layers preserved. Plus a Manager to browse and inspect any wiki part.",+  "discovery_pitch": "Convert electronic-component symbols + footprints between any two EDA tools \u2014 KiCad, Altium (written natively, no Altium needed), and EAGLE/Fusion \u2014 through one canonical adom-lbr JSON, silk/courtyard/fab layers preserved. Plus a Manager to browse and inspect any wiki part.",   "sample_prompts": [     {       "prompt": "Convert this KiCad symbol and footprint to an Altium SchLib and PcbLib",-      "label": "KiCad → Altium"+      "label": "KiCad \u2192 Altium"     },     {       "prompt": "Import this Altium footprint into the adom-lbr JSON",-      "label": "Altium → JSON"+      "label": "Altium \u2192 JSON"     },     {       "prompt": "Bundle this part into a single Altium IntLib",@@ -77,15 +74,15 @@     },     {       "prompt": "Convert this Altium SchLib and PcbLib to a KiCad symbol and footprint",-      "label": "Altium → KiCad"+      "label": "Altium \u2192 KiCad"     },     {       "prompt": "Export this adom-lbr JSON to a KiCad .kicad_sym and .kicad_mod",-      "label": "JSON → KiCad"+      "label": "JSON \u2192 KiCad"     },     {       "prompt": "Open the adom-lbr Manager to browse wiki components and view the layer stackup",       "label": "Browse parts"     }   ]-}\ No newline at end of file+}
src/manage.html+24−15
@@ -69,6 +69,7 @@   #toast{position:fixed;left:50%;bottom:22px;transform:translateX(-50%) translateY(20px);background:#0d1117;border:1px solid var(--acc);color:var(--ink);padding:8px 14px;border-radius:9px;font-size:13px;opacity:0;transition:opacity .18s,transform .18s;pointer-events:none;z-index:2000;max-width:80vw}   #toast.show{opacity:1;transform:translateX(-50%) translateY(0)}   #toast.err{border-color:var(--red)}+  #toast.success{border-color:var(--green);color:var(--green)}   /* ---- Settings modal: the Adom settings surface (settings-layout skill) ---- */   dialog.settings{width:min(680px,92vw);max-width:none;padding:0;overflow:hidden;border-radius:12px;background:var(--surface);border:1px solid var(--border);color:var(--text-body);box-shadow:0 20px 60px #000a}   dialog.settings::backdrop{background:rgba(0,0,0,.25)}@@ -239,7 +240,7 @@   <section id="say" aria-labelledby="sayTitle" hidden>     <button class="iconbtn say-close" id="sayClose" aria-label="Hide the Say it strip" title="Hide this strip. It stays hidden until you turn it back on in Settings (Say it strip)."><svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg></button>     <div class="say-head"><h2 id="sayTitle">Say it to your AI</h2>-    <span class="say-sub">You do not drive this dashboard by hand. You ask your AI, using the word <b>lbr</b>. Click a phrase to copy it, then paste it into any Adom AI thread.</span></div>+    <span class="say-sub">You do not drive this dashboard by hand. You ask your AI, using the word <b>lbr</b>. Click a phrase (or Try it) to copy it, then paste it into any Adom AI thread.</span></div>     <div class="say-list" id="phrases"></div>   </section>   <div id="panes">@@ -641,7 +642,10 @@ loadList(); loadSample();  // ===================== dock contract: LEDs, say, settings ===================== let toastT=null;-function toast(msg,err){const t=document.getElementById('toast');t.textContent=msg;t.className='show'+(err?' err':'');clearTimeout(toastT);toastT=setTimeout(()=>t.className='',2600);}+function toast(msg,err,kind){const t=document.getElementById('toast');+  const k=kind||(err?'err':'');+  t.innerHTML=(k==='success'?'<svg viewBox="0 0 24 24" width="15" height="15" style="vertical-align:-2px;margin-right:7px" aria-hidden="true"><path fill="currentColor" d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"/></svg>':'')+msg;+  t.className='show'+(k?' '+k:'');clearTimeout(toastT);toastT=setTimeout(()=>t.className='',k==='success'?4000:2600);} async function api(path,opts){const r=await fetch(path,Object.assign({},opts,{signal:AbortSignal.timeout(5000)}));return r.json();}  // ---- live LEDs in the header, from the same /api/status the dock polls ----@@ -678,23 +682,28 @@ async function loadSay(){     (r.say||[]).forEach(p=>{       const w=document.createElement('span');w.className='phrase';       const t=document.createElement('span');t.className='txt';t.textContent=p;t.title='click to copy';-      t.onclick=async()=>{toast((await copyText(p))?'Copied: "'+p+'"':'Could not copy; select it by hand',false);};-      // Try it is PARKED (ship-night ruling, 2026-08-23): the run-prompt path-      // can crash ah until the typing fix certifies, and /ai-threads calls wake-      // ah's parked backend. Copy-only until the all-clear; flip to re-enable.-      const TRY_ENABLED=false;-      if(TRY_ENABLED){-        const b=document.createElement('button');b.className='try';b.textContent='Try it';b.title="stage this phrase, unsent, into this app's own AI thread";-        b.onclick=async()=>{-          b.disabled=true;+      t.onclick=async()=>{const ok=await copyText(p);if(ok)toast('Copied to clipboard. Paste it into any AI thread.',false,'success');else toast('Could not copy; select it by hand',true);};+      // Try it copies the phrase (John's ruling, 2026-08-23): NO live AI-thread+      // opening/staging for now — zero /ai-threads calls from page or server+      // (the parked /api/try + the staging code stay dormant for the all-clear).+      const TRY_STAGING=false;+      const b=document.createElement('button');b.className='try';b.textContent='Try it';+      b.title='copies this prompt so you can paste it into any AI thread';+      b.onclick=async()=>{+        b.disabled=true;+        if(TRY_STAGING){           try{ const res=await api('api/try',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({phrase:p})});             if(res.staged){toast('Staged into '+(res.where||'your AI thread')+': "'+p+'" (press Enter there to send)');}             else{await copyText(p);toast('Copied instead: '+(res.reason||'could not stage'),true);}           }catch(e){await copyText(p);toast('Copied instead (dashboard could not reach the control API)',true);}-          b.disabled=false;-        };-        w.appendChild(t);w.appendChild(b);-      } else { w.appendChild(t); }+        } else {+          const ok=await copyText(p);+          if(ok)toast('Copied to clipboard. Paste it into any AI thread.',false,'success');+          else toast('Could not copy; select the phrase by hand and copy it',true);+        }+        b.disabled=false;+      };+      w.appendChild(t);w.appendChild(b);       el.appendChild(w);     });   }catch(e){}