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.
- package/index.js +34 -0
- 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
|
+
"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"
|