claude-code-remote-pilot 0.5.3 → 0.5.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/CHANGELOG.md +3 -3
- package/lib/SessionManager.js +5 -4
- package/lib/ui.html +11 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.5.
|
|
3
|
+
## 0.5.4 — 2026-05-06
|
|
4
4
|
|
|
5
5
|
### Fixed
|
|
6
|
-
- **Auto-resume respects clock reset time**: limit recovery now waits until the parsed `resets at HH:MM` timestamp (with next-day rollover) before sending the resume command.
|
|
7
6
|
- **Web UI respawn completed**: offline session respawn now has loading/error feedback and immediately updates session detail state after success.
|
|
7
|
+
- **Web respawn now matches CLI spawn behavior**: respawn starts a fresh session from stored path and default command semantics (same as watch-mode spawn), avoiding failures caused by stale stored command values.
|
|
8
|
+
- **Respawn loading no longer appears stuck**: web respawn now has a request timeout and surfaces a clear timeout error when the API call hangs, so the button always returns to clickable state.
|
|
8
9
|
|
|
9
10
|
---
|
|
10
11
|
|
|
@@ -12,7 +13,6 @@
|
|
|
12
13
|
|
|
13
14
|
### Fixed
|
|
14
15
|
- **Auto-resume now waits for reset time**: when Claude shows an explicit `resets at HH:MM` clock time, `Watcher` now resumes at that exact reset timestamp (including next-day rollover) instead of relying only on relative wait parsing.
|
|
15
|
-
- **Web UI respawn flow completed**: offline session respawn now shows in-button loading, inline errors, and immediately updates the detail view to the newly active session after successful `POST /api/sessions/:name/respawn`.
|
|
16
16
|
|
|
17
17
|
---
|
|
18
18
|
|
package/lib/SessionManager.js
CHANGED
|
@@ -35,9 +35,10 @@ class SessionManager {
|
|
|
35
35
|
if (this.sessions.has(sessionName)) throw new Error(`Session "${sessionName}" already exists.`);
|
|
36
36
|
|
|
37
37
|
// Kill stale tmux session from a previous crashed run
|
|
38
|
-
try {
|
|
38
|
+
try {
|
|
39
|
+
execSync(`tmux has-session -t "${sessionName}"`, { stdio: 'ignore' });
|
|
39
40
|
execSync(`tmux kill-session -t "${sessionName}"`, { stdio: 'ignore' });
|
|
40
|
-
} catch {}
|
|
41
|
+
} catch { }
|
|
41
42
|
|
|
42
43
|
execSync(`tmux new-session -d -s "${sessionName}" -c "${resolved}" "${command}"`, { stdio: 'ignore' });
|
|
43
44
|
|
|
@@ -73,13 +74,13 @@ class SessionManager {
|
|
|
73
74
|
const entry = this.sessions.get(name);
|
|
74
75
|
if (!entry) throw new Error(`Session "${name}" not found.`);
|
|
75
76
|
entry.watcher.stop();
|
|
76
|
-
try { execSync(`tmux kill-session -t "${name}"`, { stdio: 'ignore' }); } catch {}
|
|
77
|
+
try { execSync(`tmux kill-session -t "${name}"`, { stdio: 'ignore' }); } catch { }
|
|
77
78
|
this.sessions.delete(name);
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
killAll() {
|
|
81
82
|
for (const name of [...this.sessions.keys()]) {
|
|
82
|
-
try { this.kill(name); } catch {}
|
|
83
|
+
try { this.kill(name); } catch { }
|
|
83
84
|
}
|
|
84
85
|
}
|
|
85
86
|
|
package/lib/ui.html
CHANGED
|
@@ -666,8 +666,13 @@ function SessionDetailScreen({ session, onBack, onKilled, onRespawned }) {
|
|
|
666
666
|
if (respawning) return;
|
|
667
667
|
setRespawning(true);
|
|
668
668
|
setRespawnError('');
|
|
669
|
+
const controller = new AbortController();
|
|
670
|
+
const timeoutId = setTimeout(() => controller.abort(), 12000);
|
|
669
671
|
try {
|
|
670
|
-
const res = await apiFetch(`/api/sessions/${encodeURIComponent(session.name)}/respawn`, {
|
|
672
|
+
const res = await apiFetch(`/api/sessions/${encodeURIComponent(session.name)}/respawn`, {
|
|
673
|
+
method: 'POST',
|
|
674
|
+
signal: controller.signal,
|
|
675
|
+
});
|
|
671
676
|
const data = await res.json();
|
|
672
677
|
if (!res.ok) {
|
|
673
678
|
setRespawnError(data.error || 'Failed to respawn');
|
|
@@ -675,8 +680,13 @@ function SessionDetailScreen({ session, onBack, onKilled, onRespawned }) {
|
|
|
675
680
|
}
|
|
676
681
|
onRespawned(data);
|
|
677
682
|
} catch (e) {
|
|
683
|
+
if (e && e.name === 'AbortError') {
|
|
684
|
+
setRespawnError('Respawn timeout. Please try again.');
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
678
687
|
if (e.message !== 'Unauthorized') setRespawnError('Network error');
|
|
679
688
|
} finally {
|
|
689
|
+
clearTimeout(timeoutId);
|
|
680
690
|
setRespawning(false);
|
|
681
691
|
}
|
|
682
692
|
};
|
package/package.json
CHANGED