app
adom-vscode
Public Made by Adomby adom
Let Claude, Codex and Kimi drive VS Code inside your Adom container
← Commit history
release 1.1.91
9 files changed
+29−9
VERSION+1−1@@ -1 +1 @@-1.1.90+1.1.91
bin/adom-vscode⋯ 1 unchanged line ⋯
bin/hydrogen-widget-claude-usagebin/hydrogen-widget-codex-usagebin/hydrogen-widget-lib.py+25−5@@ -36,6 +36,10 @@ html,body{margin:0;height:100%%;background:transparent;color:#e6ebef;font-family .v{font-variant-numeric:tabular-nums;text-align:right} .big{font-weight:600;font-variant-numeric:tabular-nums} .err{color:#f0a060}+/* An error is a button: a click checks again now (John 2026-09-17: "make this clickable so i can+ manually refresh it after i login", and "i can't read this text its so small"). */+#wrap.act{cursor:pointer}#wrap.act:hover .err{text-decoration:underline;text-underline-offset:2px}+.checking{opacity:.7} /* Stale (last numbers while the provider is between answers): a light fade only, so the colours read the same as a fresh neighbour (John 2026-09-15: "the claude one has washed out colors"). */ #w.stale{opacity:.78}@@ -50,7 +54,7 @@ html,body{margin:0;height:100%%;background:transparent;color:#e6ebef;font-family @media (max-height:33px){ .w{font-size:clamp(7px,37vh,12px);line-height:1.2} .lbl{font-size:clamp(6px,30vh,9px)}.bar{width:clamp(24px,130vh,40px);height:clamp(4px,20vh,6px)}.v{min-width:2.4em}- .big{font-size:clamp(9px,47vh,14px)}.err{font-size:clamp(7px,33vh,10px)}+ .big{font-size:clamp(9px,47vh,14px)}.err{font-size:clamp(9px,52vh,12px)} .mark{width:clamp(10px,55vh,17px);height:clamp(10px,55vh,17px)} .cell{flex-direction:row;align-items:baseline;gap:3px} .pct{font-size:clamp(9px,66vh,14px)}.cell .lbl{font-size:clamp(6px,32vh,8px)}@@ -68,7 +72,7 @@ html,body{margin:0;height:100%%;background:transparent;color:#e6ebef;font-family .rows.hz{flex-direction:row;align-items:center;gap:6px} .row{display:grid;grid-template-columns:auto minmax(18px,1fr) auto;align-items:center;gap:3px;min-width:0} .lbl{font-size:6.5px}.row .lbl{max-width:4.2em;overflow:hidden;text-overflow:ellipsis}.bar{width:auto;height:4px}.v{font-size:8px;min-width:0}- .big{font-size:14px}.err{font-size:8px;white-space:normal;line-height:1.1;max-width:96px}+ .big{font-size:14px}.err{font-size:11.5px;white-space:normal;line-height:1.15;max-width:150px} /* Big numbers fill the 36 px the slot gives: 22 px digits over a 7 px label. */ .cell .lbl{font-size:7px}.pct{font-size:22px} /* One percentage size in every view (John 2026-09-15: Claude's all-numbers view sat at 11.6 px@@ -113,8 +117,8 @@ function render(d0){const d=d0&&d0.stale?d0.stale:d0;const el=document.getElemen if(d&&Array.isArray(d.items)&&d.items.length){const vs=viewsFor(d.items);let k=vs.findIndex(v=>v.id===curView);if(k<0){k=0;curView='rows';} el.classList.toggle('hz',curView!=='rows');el.innerHTML=renderItems(d.items,curView); tip=(tip?tip+'. ':'')+'%(title)s: '+vs[k].name+'. Click for the next view ('+(k+1)+' of '+vs.length+').';}- else{el.classList.remove('hz');el.innerHTML=%(render_js)s;}- wrap.title=tip;postWidth();}+ else{el.classList.remove('hz');el.innerHTML=%(render_js)s;tip=(d0&&d0.error?String(d0.error)+'. ':'')+'Click to check again now.';}+ wrap.classList.toggle('act',!!(d0&&d0.error));wrap.title=tip;postWidth();} /* The click's own re-render must carry the NEW view: window.__last is the last poll's copy, whose view field still names the old one, and render() adopts the server's view over the local one. Without this line a click changed the server and nothing on screen until the next poll, three@@ -123,7 +127,16 @@ function setView(id){curView=id;try{localStorage.setItem('hw.view',id);}catch(e) if(window.__last)window.__last.view=id; fetch('/view',{method:'POST',body:id}).then(r=>{if(!r.ok)throw new Error('http '+r.status);}).catch(()=>{setTimeout(()=>fetch('/view',{method:'POST',body:id}).catch(()=>{}),3000);}); if(window.__last)render(window.__last);}-document.getElementById('wrap').addEventListener('click',()=>{const d0=window.__last;const d=d0&&d0.stale?d0.stale:d0;if(!d||!Array.isArray(d.items)||!d.items.length)return;+/* CHECK NOW: POST /refresh makes the server ask the provider (or re-read the sign-in file) right away+ instead of at its next scheduled check, and answers with the fresh data. One call per click. */+let refreshing=false;+async function refreshNow(showChecking){if(refreshing)return;refreshing=true;+ if(showChecking){const el=document.getElementById('w');el.classList.remove('hz');el.innerHTML='<span class="err checking">checking…</span>';postWidth();}+ try{const r=await fetch('/refresh',{method:'POST',cache:'no-store'});if(!r.ok)throw new Error('http '+r.status);const d=await r.json();window.__last=d;render(d);}+ catch(e){tick();}finally{refreshing=false;}}+document.getElementById('wrap').addEventListener('click',()=>{const d0=window.__last;const d=d0&&d0.stale?d0.stale:d0;+ if(d0&&d0.error){if(!d||!Array.isArray(d.items)||!d.items.length){refreshNow(true);return;}refreshNow(false);}+ if(!d||!Array.isArray(d.items)||!d.items.length)return; const vs=viewsFor(d.items);const k=vs.findIndex(v=>v.id===curView);setView(vs[(k+1)%%vs.length].id);}); /* THE WIDGET DECIDES ITS WIDTH: ask the host for the intrinsic width of what is shown in the current layout (tall rows are narrow, the compact row is wide). Measured on a hidden clone laid@@ -222,6 +235,11 @@ def serve(title, data_fn, render_js, refresh_ms=60000, mark=None, align_ms=0): out = dict(cache['v']); out['view'] = cache['view'] if out.get('error'): out['retry_in'] = max(0, int(cache['wait'] - (time.time() - cache['t']))) return out+ def refresh_now():+ # A click on the widget: make the next data() call due now, whatever the schedule says.+ with lock:+ cache['t'] = 0; cache['expired_mtime'] = None+ return data() def set_view(v): with lock: cache['view'] = v@@ -237,6 +255,8 @@ def serve(title, data_fn, render_js, refresh_ms=60000, mark=None, align_ms=0): v = self.rfile.read(n).decode(errors='replace').strip()[:40] if n else '' if v: set_view(v) self._send(200, 'application/json', json.dumps({'ok': True, 'view': cache['view']}).encode())+ elif self.path.startswith('/refresh'):+ self._send(200, 'application/json', json.dumps(refresh_now()).encode()) else: self._send(404, 'text/plain', b'not found') def do_GET(self): if self.path.startswith('/data.json'): self._send(200, 'application/json', json.dumps(data()).encode())
bin/hydrogen-widget-marks.pyinstall.shpackage.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-vscode",- "version": "1.1.90",+ "version": "1.1.91", "type": "app", "description": "CLI + VS Code extension that lets AI assistants and the Hydrogen Desktop frontend drive VS Code from inside an Adom container: open files, live get/set of any setting/theme/font (no reload), native streamed exec, a frontend event queue, container identity (hd/hw), api-key status/inject, extension query/update, modes, paste screenshots, and any VS Code command via a local HTTP API on port 8821 (with port-file fallback discovery).", "license": "PROPRIETARY",
page.json+2−2@@ -4,7 +4,7 @@ "slug": "adom-vscode", "title": "adom-vscode", "brief": "Let Claude, Codex and Kimi drive VS Code inside your Adom container",- "version": "1.1.90",+ "version": "1.1.91", "license": "PROPRIETARY", "visibility": "public", "hero": {@@ -141,4 +141,4 @@ "adom-vscode-extensions", "adom-vscode-modes" ]-}+}