/ clis / _shared / desktop-commands.js
desktop-commands.js
  1  /**
  2   * Shared command factories for Electron/desktop app adapters.
  3   * Eliminates duplicate screenshot/status/new/dump implementations
  4   * across cursor, codex, chatwise, etc.
  5   */
  6  import * as fs from 'node:fs';
  7  import { cli, Strategy } from '@jackwener/opencli/registry';
  8  /**
  9   * Factory: capture DOM HTML + accessibility snapshot.
 10   */
 11  export function makeScreenshotCommand(site, displayName, extra = {}) {
 12      const label = displayName ?? site;
 13      return cli({
 14          ...extra,
 15          site,
 16          name: 'screenshot',
 17          description: `Capture a snapshot of the current ${label} window (DOM + Accessibility tree)`,
 18          domain: 'localhost',
 19          strategy: Strategy.UI,
 20          browser: true,
 21          args: [
 22              { name: 'output', required: false, help: `Output file path (default: /tmp/${site}-snapshot.txt)` },
 23          ],
 24          columns: ['Status', 'File'],
 25          func: async (page, kwargs) => {
 26              const outputPath = kwargs.output || `/tmp/${site}-snapshot.txt`;
 27              const snap = await page.snapshot({ compact: true });
 28              const html = await page.evaluate('document.documentElement.outerHTML');
 29              const htmlPath = outputPath.replace(/\.\w+$/, '') + '-dom.html';
 30              const snapPath = outputPath.replace(/\.\w+$/, '') + '-a11y.txt';
 31              fs.writeFileSync(htmlPath, html);
 32              fs.writeFileSync(snapPath, typeof snap === 'string' ? snap : JSON.stringify(snap, null, 2));
 33              return [
 34                  { Status: 'Success', File: htmlPath },
 35                  { Status: 'Success', File: snapPath },
 36              ];
 37          },
 38      });
 39  }
 40  /**
 41   * Factory: check CDP connection status.
 42   */
 43  export function makeStatusCommand(site, displayName, extra = {}) {
 44      const label = displayName ?? site;
 45      return cli({
 46          ...extra,
 47          site,
 48          name: 'status',
 49          description: `Check active CDP connection to ${label}`,
 50          domain: 'localhost',
 51          strategy: Strategy.UI,
 52          browser: true,
 53          columns: ['Status', 'Url', 'Title'],
 54          func: async (page) => {
 55              const url = await page.evaluate('window.location.href');
 56              const title = await page.evaluate('document.title');
 57              return [{ Status: 'Connected', Url: url, Title: title }];
 58          },
 59      });
 60  }
 61  /**
 62   * Factory: start a new session via Cmd/Ctrl+N.
 63   */
 64  export function makeNewCommand(site, displayName, extra = {}) {
 65      const label = displayName ?? site;
 66      return cli({
 67          ...extra,
 68          site,
 69          name: 'new',
 70          description: `Start a new ${label} session`,
 71          domain: 'localhost',
 72          strategy: Strategy.UI,
 73          browser: true,
 74          columns: ['Status'],
 75          func: async (page) => {
 76              const isMac = process.platform === 'darwin';
 77              await page.pressKey(isMac ? 'Meta+N' : 'Control+N');
 78              await page.wait(1);
 79              return [{ Status: 'Success' }];
 80          },
 81      });
 82  }
 83  /**
 84   * Factory: dump DOM + snapshot for reverse-engineering.
 85   */
 86  export function makeDumpCommand(site) {
 87      return cli({
 88          site,
 89          name: 'dump',
 90          description: `Dump the DOM and Accessibility tree of ${site} for reverse-engineering`,
 91          domain: 'localhost',
 92          strategy: Strategy.UI,
 93          browser: true,
 94          columns: ['action', 'files'],
 95          func: async (page) => {
 96              const dom = await page.evaluate('document.body.innerHTML');
 97              fs.writeFileSync(`/tmp/${site}-dom.html`, dom);
 98              const snap = await page.snapshot({ interactive: false });
 99              fs.writeFileSync(`/tmp/${site}-snapshot.json`, JSON.stringify(snap, null, 2));
100              return [
101                  {
102                      action: 'Dom extraction finished',
103                      files: `/tmp/${site}-dom.html, /tmp/${site}-snapshot.json`,
104                  },
105              ];
106          },
107      });
108  }