esque-bridge 0.6.5 → 0.6.6

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 (2) hide show
  1. package/index.js +54 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -687,8 +687,62 @@ async function probeBuildError(port) {
687
687
  return scanOutputForError(preview && preview.output);
688
688
  }
689
689
 
690
+ // Runnable previews (`expo start`, `next dev`, `vite`, …) need the project's
691
+ // dependencies on disk. The agent scaffolds package.json but deliberately does
692
+ // NOT run a slow `npm install` itself (the blueprint hands that to Esque) — so
693
+ // the very first preview would otherwise die with "module 'expo' is not
694
+ // installed" / "next: command not found". This installs them once, up front,
695
+ // with its own generous timeout so it never collides with the 60s port-wait.
696
+ // Idempotent: skipped as soon as node_modules exists.
697
+ function ensureDeps() {
698
+ return new Promise((resolve) => {
699
+ let needs;
700
+ try {
701
+ needs =
702
+ fs.existsSync(path.join(WORKDIR, 'package.json')) &&
703
+ !fs.existsSync(path.join(WORKDIR, 'node_modules'));
704
+ } catch {
705
+ needs = false;
706
+ }
707
+ if (!needs) return resolve(true);
708
+
709
+ // `--legacy-peer-deps`: AI-scaffolded Expo/RN projects routinely pin a
710
+ // React-18 app alongside test tooling that peer-wants React 19, which makes
711
+ // a strict `npm install` abort with ERESOLVE. The app runtime only needs
712
+ // the React it pins, so we tell npm to install the tree as written rather
713
+ // than fail the whole preview over a test-only peer mismatch.
714
+ console.log('[preview] installing dependencies (npm install) — first preview, this can take a few minutes…');
715
+ const proc = spawn('sh', ['-c', 'npm install --legacy-peer-deps --no-audit --no-fund'], {
716
+ cwd: WORKDIR,
717
+ env: process.env,
718
+ stdio: ['ignore', 'pipe', 'pipe'],
719
+ });
720
+ const onData = (d) => process.stdout.write(`[npm] ${d}`);
721
+ proc.stdout.on('data', onData);
722
+ proc.stderr.on('data', onData);
723
+ const timer = setTimeout(() => {
724
+ console.error('[preview] npm install exceeded 6 min — moving on (preview may fail)');
725
+ try { proc.kill('SIGKILL'); } catch { /* already gone */ }
726
+ resolve(false);
727
+ }, 360000);
728
+ proc.on('exit', (code) => {
729
+ clearTimeout(timer);
730
+ if (code === 0) console.log('[preview] dependencies installed');
731
+ else console.error(`[preview] npm install exited ${code} — preview may fail`);
732
+ resolve(code === 0);
733
+ });
734
+ proc.on('error', (e) => {
735
+ clearTimeout(timer);
736
+ console.error('[preview] npm install error:', e.message);
737
+ resolve(false);
738
+ });
739
+ });
740
+ }
741
+
690
742
  async function startPreview(cmd, port) {
691
743
  killPreview();
744
+ // Make sure node_modules exists before the dev server tries to boot.
745
+ await ensureDeps();
692
746
  console.log(`[preview] starting: ${cmd} (port ${port})`);
693
747
  const proc = spawn('sh', ['-c', cmd], { cwd: WORKDIR, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] });
694
748
  preview = { port, proc, kind: null, url: null, tunnel: null, tunnelProc: null, output: '', buildError: null };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esque-bridge",
3
- "version": "0.6.5",
3
+ "version": "0.6.6",
4
4
  "description": "Desktop-side receiver for the Esque Agent mobile app. Pairs your phone with a local coding-agent CLI (Claude Code, Codex, Aider, or any custom command) via a tunnel + QR code, so prompts run through your subscription instead of per-token API billing.",
5
5
  "bin": {
6
6
  "esque-bridge": "index.js"