claude-code-remote-pilot 0.5.8 → 0.5.9
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/claude-pilot.js +3 -0
- package/lib/WebServer.js +9 -0
- package/lib/ui.html +15 -0
- package/package.json +1 -1
package/bin/claude-pilot.js
CHANGED
|
@@ -459,6 +459,7 @@ ${HELP}`);
|
|
|
459
459
|
console.log(' Starting cloudflared tunnel...');
|
|
460
460
|
webServer.startTunnel().then(publicUrl => {
|
|
461
461
|
console.log(` ✓ Tunnel ready: ${publicUrl}`);
|
|
462
|
+
console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
|
|
462
463
|
if (!webPassword) console.log(' ⚠ Reminder: no password set. Restart with a password for security.');
|
|
463
464
|
if (telegram.token && telegram.chatId) {
|
|
464
465
|
notifier.send(telegram.token, telegram.chatId,
|
|
@@ -538,6 +539,7 @@ ${HELP}`);
|
|
|
538
539
|
console.log(' Starting cloudflared tunnel...');
|
|
539
540
|
webServer.startTunnel().then(publicUrl => {
|
|
540
541
|
console.log(` ✓ Tunnel ready: ${publicUrl}`);
|
|
542
|
+
console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
|
|
541
543
|
if (telegram.token && telegram.chatId) {
|
|
542
544
|
notifier.send(telegram.token, telegram.chatId,
|
|
543
545
|
`Claude Remote Pilot tunnel ready: ${publicUrl}${webServer.password ? ' (password protected)' : ' ⚠ no password set'}`);
|
|
@@ -564,6 +566,7 @@ ${HELP}`);
|
|
|
564
566
|
console.log(' Starting cloudflared tunnel...');
|
|
565
567
|
webServer.startTunnel().then(publicUrl => {
|
|
566
568
|
console.log(` ✓ Tunnel ready: ${publicUrl}`);
|
|
569
|
+
console.log(' Note: first visit may show a Cloudflare warning — click "Proceed" to open the dashboard.');
|
|
567
570
|
if (!password) console.log(' ⚠ Reminder: add a password with: web <port> <host> <password> --tunnel');
|
|
568
571
|
if (telegram.token && telegram.chatId) {
|
|
569
572
|
notifier.send(telegram.token, telegram.chatId,
|
package/lib/WebServer.js
CHANGED
|
@@ -18,6 +18,7 @@ class WebServer {
|
|
|
18
18
|
this.server = null;
|
|
19
19
|
this._clients = new Set();
|
|
20
20
|
this._broadcastInterval = null;
|
|
21
|
+
this._heartbeatInterval = null;
|
|
21
22
|
this._tunnelProcess = null;
|
|
22
23
|
this._tunnelUrl = null;
|
|
23
24
|
}
|
|
@@ -201,6 +202,7 @@ class WebServer {
|
|
|
201
202
|
'Content-Type': 'text/event-stream',
|
|
202
203
|
'Cache-Control': 'no-cache',
|
|
203
204
|
'Connection': 'keep-alive',
|
|
205
|
+
'X-Accel-Buffering': 'no', // prevent Cloudflare/nginx from buffering the stream
|
|
204
206
|
});
|
|
205
207
|
this._clients.add(res);
|
|
206
208
|
res.write(`data: ${JSON.stringify(this._buildAllSessions())}\n\n`);
|
|
@@ -217,6 +219,12 @@ class WebServer {
|
|
|
217
219
|
});
|
|
218
220
|
|
|
219
221
|
this._broadcastInterval = setInterval(() => this._broadcast(), 3000);
|
|
222
|
+
// Keep SSE connections alive through proxies (Cloudflare timeout is ~100s)
|
|
223
|
+
this._heartbeatInterval = setInterval(() => {
|
|
224
|
+
for (const res of this._clients) {
|
|
225
|
+
try { res.write(': heartbeat\n\n'); } catch { this._clients.delete(res); }
|
|
226
|
+
}
|
|
227
|
+
}, 20000);
|
|
220
228
|
this.server.listen(this.port, this.host);
|
|
221
229
|
return this.port;
|
|
222
230
|
}
|
|
@@ -259,6 +267,7 @@ class WebServer {
|
|
|
259
267
|
stop() {
|
|
260
268
|
this.stopTunnel();
|
|
261
269
|
clearInterval(this._broadcastInterval);
|
|
270
|
+
clearInterval(this._heartbeatInterval);
|
|
262
271
|
for (const res of this._clients) { try { res.end(); } catch {} }
|
|
263
272
|
this._clients.clear();
|
|
264
273
|
if (this.server) this.server.close();
|
package/lib/ui.html
CHANGED
|
@@ -1094,6 +1094,21 @@ function App() {
|
|
|
1094
1094
|
return () => { if (esRef.current) esRef.current.close(); };
|
|
1095
1095
|
}, []);
|
|
1096
1096
|
|
|
1097
|
+
// Fallback polling — loads sessions immediately and keeps them fresh when
|
|
1098
|
+
// SSE is blocked (e.g. through a Cloudflare tunnel that buffers streams).
|
|
1099
|
+
useEffect(() => {
|
|
1100
|
+
let mounted = true;
|
|
1101
|
+
const poll = () => {
|
|
1102
|
+
apiFetch('/api/sessions', { cache: 'no-store' })
|
|
1103
|
+
.then(r => r.json())
|
|
1104
|
+
.then(data => { if (mounted) setSessions(data); })
|
|
1105
|
+
.catch(() => {});
|
|
1106
|
+
};
|
|
1107
|
+
poll();
|
|
1108
|
+
const t = setInterval(poll, 5000);
|
|
1109
|
+
return () => { mounted = false; clearInterval(t); };
|
|
1110
|
+
}, []);
|
|
1111
|
+
|
|
1097
1112
|
const handleLogin = useCallback(() => {
|
|
1098
1113
|
setNeedsLogin(false);
|
|
1099
1114
|
apiFetch('/api/status').then(r => r.json()).then(setServerStatus).catch(() => {});
|
package/package.json
CHANGED