feat: plan-approval overlay, auth-expiry handling, cert download, login reset
- Add a dedicated plan-approval bottom sheet (interactive-prompt) driven by ExitPlanMode's now-4-option layout (Claude Code v2.1.177), with approve/YOLO/reject/feedback wired through respondPlan(requestId). - PermissionManager: stop auto-expiring AskUserQuestion/plan prompts and stop releasing pending prompts on client disconnect — they reflect real CLI state and must survive reconnects. - Detect server-rejected tokens (401/403 or failed WS handshake) and bounce back to the login screen via a new AUTH_EXPIRED_EVENT. - Add `/cert` endpoint + Settings entry so phones can download/trust the self-signed HTTPS cert directly; fix cert IP detection on non-macOS hosts. - Add `clawtap reset-login` command and `/api/auth/reset-attempts` endpoint to clear login rate-limit lockouts. - Codex adapter: only forward recognized keystrokes/option indices to tmux, never the synthetic "deny" dismissal signal. - PWA: actively poll for service-worker updates (iOS standalone apps don't reliably check on navigation). - update-service.sh: install tmux if missing, prompt to create the env file instead of failing, add --skip-firewall, and improve logging.
This commit is contained in:
+11
-1
@@ -20,21 +20,26 @@ export class WsClient {
|
||||
private activeAdapter: string | null = null;
|
||||
private visibilityHandler: (() => void) | null = null;
|
||||
private hiddenSince: number | null = null;
|
||||
private openedThisAttempt = false;
|
||||
private onAuthCheckNeeded: (() => void) | null = null;
|
||||
|
||||
constructor(token: string, onMessage: MessageHandler, onStatus: StatusHandler) {
|
||||
constructor(token: string, onMessage: MessageHandler, onStatus: StatusHandler, onAuthCheckNeeded?: () => void) {
|
||||
const proto = location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
this.url = `${proto}://${location.host}/ws?token=${encodeURIComponent(token)}`;
|
||||
this.onMessage = onMessage;
|
||||
this.onStatus = onStatus;
|
||||
this.onAuthCheckNeeded = onAuthCheckNeeded || null;
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.shouldReconnect = true;
|
||||
this.openedThisAttempt = false;
|
||||
this.onStatus('connecting');
|
||||
|
||||
this.ws = new WebSocket(this.url);
|
||||
|
||||
this.ws.onopen = () => {
|
||||
this.openedThisAttempt = true;
|
||||
this.reconnectDelay = 1000;
|
||||
this.onStatus('connected');
|
||||
|
||||
@@ -68,6 +73,11 @@ export class WsClient {
|
||||
|
||||
this.ws.onclose = () => {
|
||||
this.onStatus('disconnected');
|
||||
// The handshake itself failed (e.g. server rejected the auth token) —
|
||||
// check whether our token is still valid rather than reconnecting forever.
|
||||
if (!this.openedThisAttempt) {
|
||||
this.onAuthCheckNeeded?.();
|
||||
}
|
||||
if (this.shouldReconnect) {
|
||||
this.onStatus('reconnecting');
|
||||
setTimeout(() => this.connect(), this.reconnectDelay);
|
||||
|
||||
Reference in New Issue
Block a user