feat: ClawTap v0.1.0 — initial release

Multi-adapter mobile UI for AI coding assistants.
Supports Claude Code, Codex CLI, and Gemini CLI through one interface.

Features:
- Real-time bidirectional sync via tmux + WebSocket
- Cross-AI review (send one AI's output to another for review)
- Multi-review tabs with minimize/expand
- Push notifications (PWA) with smart session-aware filtering
- Three-channel event system (hooks, file watcher, pane monitor)
- Voice input, image paste, draft persistence
- Terminal-native design (JetBrains Mono, dark theme, pixel art claw)
- CLI with --adapter flag on every command
- Zero-overhead fire-and-forget hooks
This commit is contained in:
kuannnn
2026-03-18 10:24:45 +08:00
commit 42861ea7fa
151 changed files with 33897 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
import crypto from 'crypto';
import type { ServerMessage } from '../types/messages.js';
/**
* ClientConnection — abstract base class for transport-agnostic client connections.
*
* Each connected client (WebSocket, SSE, etc.) is represented by a ClientConnection.
* SessionManager works exclusively with this abstraction — never with raw WebSocket.
*/
export abstract class ClientConnection {
readonly clientId: string = crypto.randomUUID();
readonly transportName: string;
sessionId: string | null = null;
onDisconnect: ((conn: ClientConnection) => void) | null = null;
constructor(transportName: string) {
this.transportName = transportName;
}
/** Send a message to this client. Implementation handles serialization. */
abstract send(message: ServerMessage): void;
/** Check if the connection is still alive. */
abstract isAlive(): boolean;
/** Close the connection. */
close(): void {}
/** Filter: should this client receive a given message? Default: yes. */
shouldReceive(_message: ServerMessage): boolean { return true; }
/** Send a pre-serialized JSON string. Default fallback parses and calls send(). */
sendRaw(json: string): void { this.send(JSON.parse(json)); }
/** Notify the disconnect handler (called by subclass when connection drops). */
notifyDisconnect(): void { this.onDisconnect?.(this); }
}