add pane subsystem to the daemon + IPC event broadcast
Implements the Tier-1 pane subsystem from D-006: spawn / list / focus / close / write / resize / tail commands, plus pane.spawned / output / exit / resized / focused / closed events. PaneRegistry owns per-pane PtySession lifecycles and id generation (p_N); a DaemonEventSink seam keeps pane code decoupled from the IPC server package. DaemonServer.broadcast() fans events out to every connected client. Per-client subsystem/id filtering (`tail --filter pane:p_7`) is deferred — Tier 1 broadcasts everything and the subscriber discards. Panes carry a `kind:` field (terminal | claude). Step 7 (builtin.claude) adds the claude-specific pane flow on top of this generic substrate — the subsystem itself stays neutral. 14 new core tests: registry unit coverage (spawn → pane.spawned event, output → base64 events, write/resize/close round-trips, idempotent close, claude kind on the wire) plus dispatcher coverage (argv validation, unknown-id → not-found, text vs bytes_b64, etc). All 37 core tests pass in ~3s under test-core. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+18
-2
@@ -8,8 +8,7 @@ typedef RequestDispatcher = Future<IpcResponse> Function(IpcRequest request);
|
||||
|
||||
/// Unix-socket JSON-lines server. Each connection is an independent
|
||||
/// bidirectional line-framed stream: client writes requests, daemon
|
||||
/// writes responses (and events, later). Tier 0 handles request→response
|
||||
/// only; event broadcasting lands with the first feature that emits.
|
||||
/// writes responses + events on the same socket.
|
||||
class DaemonServer {
|
||||
DaemonServer({
|
||||
required this.socketPath,
|
||||
@@ -22,6 +21,23 @@ class DaemonServer {
|
||||
ServerSocket? _server;
|
||||
final Set<Socket> _clients = {};
|
||||
|
||||
/// Broadcast [event] to every currently-connected client.
|
||||
///
|
||||
/// Future tuning: per-client subsystem/id filter (`tail --filter
|
||||
/// pane:p_7`). For Tier 1 every client sees everything. Sockets
|
||||
/// that error on write are silently dropped; the client's read side
|
||||
/// will notice the close.
|
||||
void broadcast(IpcEvent event) {
|
||||
final line = event.encode();
|
||||
for (final c in List<Socket>.from(_clients)) {
|
||||
try {
|
||||
c.writeln(line);
|
||||
} catch (_) {
|
||||
_clients.remove(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> start() async {
|
||||
final addr = InternetAddress(socketPath, type: InternetAddressType.unix);
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user