Skip to content

Fix Fish terminal capability query before xterm attaches - #1597

Open
smsunarto wants to merge 1 commit into
get-bb:mainfrom
smsunarto:bb/investigate-fish-primary-device-warning-thr_u2hdb93w8w
Open

Fix Fish terminal capability query before xterm attaches#1597
smsunarto wants to merge 1 commit into
get-bb:mainfrom
smsunarto:bb/investigate-fish-primary-device-warning-thr_u2hdb93w8w

Conversation

@smsunarto

Copy link
Copy Markdown
Contributor

Summary

Handle Primary Device Attributes (DA1) queries at the host PTY boundary.

This prevents Fish from waiting 10 seconds and showing:

fish could not read response to Primary Device Attribute query

Problem

bb starts the host PTY before the browser terminal attaches. This lets terminal processes start immediately, retain their session, and buffer output while no terminal view is open.

During startup, Fish sends a DA1 query (ESC[c or ESC[0c) and waits for a terminal emulator to answer. xterm.js supports this query, but it cannot answer before it attaches to the PTY.

Forwarding the query through replay does not provide a safe fix. Replayed output can be processed again after reconnects, which could produce duplicate terminal responses.

Solution

The host daemon now:

  • detects both supported DA1 query forms;
  • recognizes queries split across output chunks;
  • writes the xterm-compatible ESC[?1;2c response directly to the PTY;
  • removes handled queries from live and replayed output, which prevents duplicate browser responses;
  • preserves near matches and incomplete queries if the PTY exits.

This is intentionally a small protocol-specific handler. Adding a headless terminal emulator package would introduce parser state and a larger dependency for one startup query. If detached terminal emulation needs to support more queries later, the code comments identify @xterm/headless as the correct replacement.

The host daemon protocol version increases from 119 to 120 so enrolled machines cannot use old terminal semantics with the updated server.

Verification

  • Host daemon tests: 557 passed
  • Host daemon contract tests: 49 passed
  • Turbo typechecks passed for both affected packages
  • git diff --check passed
  • Live Fish 4.8.1 session:
    • prompt appeared normally;
    • no warning appeared after 11 seconds;
    • no handled DA1 query remained in terminal replay output
  • Electron dev build started successfully

AGENT GENERATED: by GPT-5.4

Handle DA1 queries at the host PTY boundary so shells do not time out while the browser terminal is detached. Remove handled queries from replay output to prevent duplicate responses after reconnects.

Amp-Thread-ID: https://ampcode.com/threads/T-019ffee9-be44-75c0-bd8a-1c653b61f62a
Co-authored-by: Amp <amp@ampcode.com>
@bb-slop-cop

bb-slop-cop Bot commented Aug 14, 2026

Copy link
Copy Markdown

🚨 SLOP COP 🚨 · review

I am SlopCop. I am reviewing this pull request now. I will check security, code quality, architecture, performance, and test coverage.

);
session.pendingPrimaryDeviceAttributesQuery = result.pendingQuery;
for (let index = 0; index < result.queryCount; index += 1) {
session.pty.write(PRIMARY_DEVICE_ATTRIBUTES_RESPONSE);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 slopcop/review — High: Batch and bound the automatic DA1 replies.

This loop calls pty.write once for each query. A 65,535-byte event can contain 21,845 ESC[c queries. Node-pty copies each reply into its unbounded Unix write queue. A terminal process can therefore create many queue items and exhaust memory in the shared host daemon.

Use one bounded write, or a small fixed number of bounded writes. Add a flood test that verifies the write count and response bytes.

@bb-slop-cop bb-slop-cop Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚨 SLOP COP 🚨 · review

Plain-English summary

This change lets the host daemon answer Fish's early terminal identity query before the browser terminal starts. It removes handled queries from replay. This prevents Fish's startup timeout and duplicate browser answers. It also changes protocol version 119 to 120.

Finding

High — Batch and bound automatic DA1 replies.

At terminal-manager.ts:865-866, the code calls pty.write once for each matched query. A 65,535-byte event can hold 21,845 ESC[c queries. Node-pty copies every reply into an unbounded write queue. A terminal process can create many queue items and exhaust memory in the shared host daemon. This can affect other terminals.

Use one bounded write, or a small fixed number of bounded writes. Add a flood test that verifies bounded writes and correct response bytes.

Other review results

  • The security review found no other issue.
  • The code review found no correctness issue in the parser, replay logic, exit flush, or protocol change.
  • The architecture scan found no duplicate host-side DA1 handler. The small local handler is suitable for one query. Use one headless emulator if detached protocol support expands.
  • Exact-head Turbo tests passed: 557 host-daemon tests and 49 contract tests.
  • Exact-head Turbo type checks passed for both changed packages.
  • All current GitHub checks passed.
  • A live Fish test was unavailable because Fish is not installed. The fake-PTY tests cover the pre-attach boundary behavior.

I used GitHub's comment-only review state. I did not approve or request changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant