glidercli 0.3.13 → 0.3.14

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.
package/bin/glider.js CHANGED
@@ -700,6 +700,66 @@ async function cmdRestart() {
700
700
  await cmdStart();
701
701
  }
702
702
 
703
+ // POTEMKIN-PATCH v1: automate the extension reload + tab re-attachment loop
704
+ // so operators don't have to click chrome://extensions after every code change.
705
+ // Bootstrap cost: one manual reload after installing this handler for the first time.
706
+ async function cmdReloadExt() {
707
+ try {
708
+ const r = await postExtension({ method: 'reloadSelf', params: {} });
709
+ log.ok(`Extension reload triggered (persisted ${r.result?.persisted ?? '?'} tab URLs).`);
710
+ log.info('Waiting 4s for extension to boot back up + reconnect...');
711
+ await new Promise(x => setTimeout(x, 4000));
712
+ // Extension reboots → autoAttachActiveTab restores from chrome.storage
713
+ // Confirm state
714
+ const st = await httpGetJson('/status');
715
+ log.ok(`relay reconnected: extension=${st.extension} targets=${st.targets}`);
716
+ } catch (e) {
717
+ log.fail(`reload-ext failed: ${e.message}`);
718
+ log.info('First-time bootstrap: open your browser extensions page and reload Glider (one time only).');
719
+ }
720
+ }
721
+
722
+ async function cmdAttachAll(filter) {
723
+ try {
724
+ const r = await postExtension({ method: 'attachAllTabs', params: filter ? { urlSubstring: filter } : {} });
725
+ log.ok(`attach-all: attached=${r.result?.attached ?? '?'} skipped=${r.result?.skipped ?? '?'} failed=${r.result?.failed ?? '?'} total_connected=${r.result?.total_connected ?? '?'}`);
726
+ } catch (e) {
727
+ log.fail(`attach-all failed: ${e.message}`);
728
+ }
729
+ }
730
+
731
+ // Helper: POST to relay's /extension endpoint (already exists in bserve.js)
732
+ async function postExtension(body) {
733
+ return new Promise((resolve, reject) => {
734
+ const data = JSON.stringify(body);
735
+ const req = http.request({
736
+ hostname: '127.0.0.1', port: 19988, path: '/extension', method: 'POST',
737
+ headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(data) }
738
+ }, (res) => {
739
+ let s = '';
740
+ res.on('data', c => s += c);
741
+ res.on('end', () => {
742
+ try {
743
+ const j = JSON.parse(s);
744
+ if (j.error) reject(new Error(j.error.message || j.error));
745
+ else resolve(j);
746
+ } catch(e) { reject(new Error('bad JSON from /extension: ' + s.slice(0,200))); }
747
+ });
748
+ });
749
+ req.on('error', reject);
750
+ req.write(data); req.end();
751
+ });
752
+ }
753
+
754
+ async function httpGetJson(pathStr) {
755
+ return new Promise((resolve, reject) => {
756
+ http.get({ hostname: '127.0.0.1', port: 19988, path: pathStr }, (res) => {
757
+ let s = ''; res.on('data', c => s += c);
758
+ res.on('end', () => { try { resolve(JSON.parse(s)); } catch(e) { reject(e); } });
759
+ }).on('error', reject);
760
+ });
761
+ }
762
+
703
763
  // Daemon management - runs forever, respawns on crash
704
764
  async function cmdInstallDaemon() {
705
765
  const home = os.homedir();
@@ -2188,6 +2248,13 @@ async function main() {
2188
2248
  case 'restart':
2189
2249
  await cmdRestart();
2190
2250
  break;
2251
+ case 'reload-ext':
2252
+ case 'reload-extension':
2253
+ await cmdReloadExt();
2254
+ break;
2255
+ case 'attach-all':
2256
+ await cmdAttachAll(args[1]); // optional URL substring filter, e.g. 'microsoft.com'
2257
+ break;
2191
2258
  case 'install':
2192
2259
  await cmdInstallDaemon();
2193
2260
  break;
package/lib/bserve.js CHANGED
@@ -294,6 +294,14 @@ async function routeCDPCommand({ method, params, sessionId }) {
294
294
  };
295
295
 
296
296
  case 'Target.setAutoAttach':
297
+ // OOPIF-PATCH v1: forward to extension when session-scoped (per-tab autoAttach)
298
+ // so chrome.debugger emits Target.attachedToTarget for OOPIF children.
299
+ // When no sessionId (browser-level call), fall through to the existing
300
+ // "replay attachedToTarget for connectedTargets" branch in the ws handler above.
301
+ if (sessionId) {
302
+ break; // forward to extension
303
+ }
304
+ return {};
297
305
  case 'Target.setDiscoverTargets':
298
306
  return {};
299
307
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "glidercli",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "Browser automation CLI. Control Chrome from terminal via CDP, run YAML task files, autonomous loops until completion.",
5
5
  "main": "index.js",
6
6
  "bin": {