symbiot 0.28.1 → 0.28.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.mjs +9 -5
  2. package/package.json +1 -1
  3. package/ui.mjs +13 -1
package/index.mjs CHANGED
@@ -1559,16 +1559,20 @@ async function cmdApp() {
1559
1559
  if (u.pathname === "/api/connect" && req.method === "POST") { return json(res, await connectProvider(await readBody(req))); }
1560
1560
  if (u.pathname === "/api/ping") { if (u.searchParams.get("fresh") === "1") await checkLatest(); return json(res, { version: VERSION, started: SERVER_STARTED, latest: LATEST_VERSION, newer: semverGt(LATEST_VERSION, VERSION) }); }
1561
1561
  if (u.pathname === "/api/update" && req.method === "POST") {
1562
- // Install the newest symbiot, then relaunch this same app (same port +
1563
- // token => same URL) and exit. The open page's heartbeat reconnects and
1564
- // reloads to the new version. No terminal, no reopening the window.
1565
- const inst = process.platform === "win32" ? "npm i -g symbiot@latest" : "npm install -g symbiot@latest";
1562
+ // Install the EXACT newest version (not the `latest` tag, which npm's
1563
+ // cache/propagation can resolve stale — that caused an update loop where
1564
+ // the install kept re-fetching the same old version), then relaunch this
1565
+ // same app (same port+token => same URL) and exit. --prefer-online skips
1566
+ // a stale cached packument. The page's heartbeat reconnects and reloads.
1567
+ const target = LATEST_VERSION && semverGt(LATEST_VERSION, VERSION) ? LATEST_VERSION : "latest";
1568
+ const pkg = "symbiot@" + target;
1569
+ const inst = (process.platform === "win32" ? "npm i -g " : "npm install -g ") + pkg + " --prefer-online";
1566
1570
  const e = track("symbiot update", inst, homedir(), (code) => {
1567
1571
  if (code !== 0) return;
1568
1572
  try { const ch = spawn(process.execPath, process.argv.slice(1), { detached: true, stdio: "ignore", env: process.env }); ch.unref(); } catch {}
1569
1573
  setTimeout(() => process.exit(0), 1200);
1570
1574
  });
1571
- return json(res, { started: true, id: e ? e.id : "" });
1575
+ return json(res, { started: true, id: e ? e.id : "", target });
1572
1576
  }
1573
1577
  if (u.pathname === "/api/quit") { res.writeHead(200); res.end("bye"); setTimeout(() => process.exit(0), 150); return; }
1574
1578
  } catch (e) { res.writeHead(500, { "content-type": "application/json" }); res.end(JSON.stringify({ error: String((e && e.message) || e) })); return; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "symbiot",
3
- "version": "0.28.1",
3
+ "version": "0.28.2",
4
4
  "description": "Your week, written from your real work. Reads your local git and writes it up with the AI of your choice — Claude, OpenAI, Gemini, or a local model.",
5
5
  "type": "module",
6
6
  "bin": {
package/ui.mjs CHANGED
@@ -455,6 +455,18 @@ function heartbeat(fresh){
455
455
  else if(p.started!==SRV_STARTED){location.reload();return;}
456
456
  if(srvDown){location.reload();return;}
457
457
  if(updBusy)return;
458
+ // Loop guard: if we already tried to update to this version and we're still
459
+ // not on it after the restart, the install isn't advancing — stop offering
460
+ // the button (which just loops) and tell them to update manually.
461
+ var tried=null;try{tried=localStorage.getItem('symbiot_update_tried');}catch(e){}
462
+ if(tried){
463
+ if(p.version!==tried){try{localStorage.removeItem('symbiot_update_tried');}catch(e){} } // advanced → success, clear
464
+ else if(p.latest&&p.newer){ // still on the same version → the install didn't advance
465
+ b.className='updatebar reconnect show';
466
+ b.innerHTML="Auto-update to "+esc(p.latest)+" didn't take (still on "+esc(p.version)+"). Run <code>npm install -g symbiot@latest</code> in a terminal, then restart.";
467
+ return;
468
+ }
469
+ }
458
470
  if(p.latest&&p.newer){
459
471
  b.className='updatebar show';
460
472
  b.innerHTML="A new Symbiot ("+esc(p.latest)+") is available &mdash; you're on "+esc(p.version)+". <button id='doupd'>Update &amp; restart</button>";
@@ -462,7 +474,7 @@ function heartbeat(fresh){
462
474
  }else{b.className='updatebar';}
463
475
  }).catch(function(){srvDown=true;var b=ubar();b.className='updatebar reconnect show';b.textContent='Reconnecting to Symbiot…';});
464
476
  }
465
- function doUpdate(){updBusy=true;var b=ubar();b.className='updatebar show';b.textContent='Updating & restarting… this page will reload itself when it is back.';api('/api/update',{});}
477
+ function doUpdate(){updBusy=true;try{localStorage.setItem('symbiot_update_tried',document.getElementById('ver').textContent.replace(/^v/,''));}catch(e){}var b=ubar();b.className='updatebar show';b.textContent='Updating & restarting… this page will reload itself when it is back.';api('/api/update',{});}
466
478
  setInterval(heartbeat,4000);heartbeat(true);
467
479
  window.addEventListener('focus',function(){heartbeat(true);}); // re-check for updates when you come back to the window
468
480
  initGraphEvents();syncP();refresh();loadMap();loadAgentCfg();loadScanRoots();