esque-bridge 0.6.3 → 0.6.4

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 +34 -0
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -792,10 +792,35 @@ function gcJobs() {
792
792
  // never keeps the process alive on its own.
793
793
  setInterval(gcJobs, 60_000).unref?.();
794
794
 
795
+ // Ping the phone via Expo's push service when a job finishes, so the user is
796
+ // notified even with the app backgrounded or closed (iOS suspends the phone's
797
+ // polling loop). The data payload mirrors the app's local-notification schema
798
+ // so a tapped push lands in the right session. No-op for non-Expo tokens.
799
+ async function sendExpoPush(token, kind, sessionId, title, message) {
800
+ if (!token || !String(token).startsWith('ExponentPushToken[')) return;
801
+ try {
802
+ await fetch('https://exp.host/--/api/v2/push/send', {
803
+ method: 'POST',
804
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
805
+ body: JSON.stringify({
806
+ to: token,
807
+ title,
808
+ body: String(message || '').replace(/\s+/g, ' ').trim().slice(0, 178) || 'Tap to review.',
809
+ sound: 'default',
810
+ priority: 'high',
811
+ data: { kind, sessionId },
812
+ }),
813
+ });
814
+ } catch (e) {
815
+ console.error('[push] send failed:', e.message);
816
+ }
817
+ }
818
+
795
819
  async function executeHandler(req, res) {
796
820
  const body = req.body || {};
797
821
  const prompt = String(body.prompt || '');
798
822
  const esqueSessionId = body.sessionId ?? null;
823
+ const pushToken = typeof body.pushToken === 'string' ? body.pushToken : null;
799
824
  if (!prompt.trim()) {
800
825
  return res.status(400).json({ text: 'Empty prompt.', status: 'blocked' });
801
826
  }
@@ -826,6 +851,14 @@ async function executeHandler(req, res) {
826
851
  console.log(
827
852
  `[bridge] done job=${jobId} ${result.isError ? 'blocked' : 'finished'}`,
828
853
  );
854
+ const ok = !result.isError;
855
+ sendExpoPush(
856
+ pushToken,
857
+ ok ? 'finished' : 'blocked',
858
+ esqueSessionId,
859
+ ok ? '✅ Step complete' : '⚠️ Agent needs you',
860
+ result.text,
861
+ );
829
862
  })
830
863
  .catch((err) => {
831
864
  jobs.set(jobId, {
@@ -834,6 +867,7 @@ async function executeHandler(req, res) {
834
867
  createdAt: Date.now(),
835
868
  });
836
869
  console.error(`[bridge] error job=${jobId}:`, err.message);
870
+ sendExpoPush(pushToken, 'blocked', esqueSessionId, '⚠️ Agent hit an error', err.message);
837
871
  });
838
872
  return;
839
873
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "esque-bridge",
3
- "version": "0.6.3",
3
+ "version": "0.6.4",
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"