Commit c0d157e

Eric Bower  ·  2026-10-15 23:40:49 -0400 EDT
parent 2d23c0d
fix: replace has_had_client with clearing write_buf when is_terminal=false

When a client connects, daemonLoop may broadcast raw PTY output into
client.write_buf between accept() and handleInit().  Clearing write_buf avoids
duplicating the initial output of forwarding already answered DA queries.  This
means we can always send terminal snapshot now.
1 files changed,  +6, -10
+6, -10
......@@ -598,7 +598,6 @@ pub const Daemon = struct {
598598 cwd_buf: [std.fs.max_path_bytes]u8 = undefined,
599599 cwd_path_buf: [std.fs.max_path_bytes]u8 = undefined,
600600 has_pty_output: bool = false,
601- has_had_client: bool = false,
602601 created_at: u64, // unix timestamp (ns)
603602 is_task_mode: bool = false, // flag for when session is run as a task
604603 task_id: [4]u8 = undefined,
......@@ -957,6 +956,10 @@ pub const Daemon = struct {
957956 ) !void {
958957 if (payload.len != @sizeOf(ipc.Resize)) return;
959958
959+ if (!client.is_terminal) {
960+ client.write_buf.clearRetainingCapacity();
961+ client.has_pending_output = false;
962+ }
960963 client.is_terminal = true;
961964
962965 if (self.leader_client_fd == null) {
......@@ -975,9 +978,7 @@ pub const Daemon = struct {
975978 try resizeTerm(gpa, term, resize.cols, resize.rows);
976979 }
977980
978- // Only serialize on re-attach (has_had_client), not first attach, to avoid
979- // interfering with shell initialization (DA1 queries, etc.)
980- if (self.has_pty_output and self.has_had_client) {
981+ if (self.has_pty_output) {
981982 const cursor = &term.screens.active.cursor;
982983 std.log.debug(
983984 "cursor before serialize: x={d} y={d} pending_wrap={}",
......@@ -1009,16 +1010,13 @@ pub const Daemon = struct {
10091010 // incremental renderers (Ink, Claude Code, etc.) know to repaint.
10101011 // If the size changed, TIOCSWINSZ above already sent SIGWINCH; if the size
10111012 // was unchanged, the kernel suppressed it, so signal the pgrp explicitly.
1012- if (self.has_pty_output and self.has_had_client) {
1013+ if (self.has_pty_output) {
10131014 var pgrp: lib_posix.pid_t = 0;
10141015 if (cross.c.ioctl(pty_fd, cross.c.TIOCGPGRP, &pgrp) == 0 and pgrp > 0) {
10151016 lib_posix.kill(-pgrp, .WINCH) catch {};
10161017 }
10171018 }
10181019
1019- // Mark that we've had a client init, so subsequent clients get terminal state
1020- self.has_had_client = true;
1021-
10221020 std.log.debug("init resize rows={d} cols={d}", .{ resize.rows, resize.cols });
10231021 }
10241022 }
......@@ -1199,7 +1197,6 @@ pub const Daemon = struct {
11991197
12001198 try ipc.appendMessage(gpa, &client.write_buf, .Ack, "");
12011199 client.has_pending_output = true;
1202- self.has_had_client = true;
12031200 std.log.debug("run command len={d}", .{payload.len});
12041201 }
12051202
......@@ -1306,7 +1303,6 @@ pub const Daemon = struct {
13061303
13071304 try ipc.appendMessage(gpa, &client.write_buf, .Ack, "");
13081305 client.has_pending_output = true;
1309- self.has_had_client = true;
13101306 std.log.debug(
13111307 "write command len={d} file_path={s}",
13121308 .{ file_content.len, file_path },