[BUG] Agent terminal PTY width tied to chat panel causes output corruption

Summary

The agentic chat terminal spawns a PTY whose column width is determined by the chat panel’s pixel width in the VS Code sidebar. This causes ConPTY hard-wrap line breaks that corrupt CLI output, making it difficult or impossible for the agent to parse command results. The issue wastes tokens on retries and workarounds.

Environment

  • Version: 1.20.5
  • OS: Windows 11
  • Shell: PowerShell 7 (pwsh)
  • Repro frequency: 100% — every command with output exceeding the column width

Steps to Reproduce

  1. Open Google Antigravity
  2. Keep the chat panel at a small width (200 px or less)
  3. Open the agentic chat and ask the agent to run a command that produces moderately long output lines, such as:
    go test ./... -cover -count=1
    
  4. Observe the output returned to the agent

Expected Behavior

Clean, linear output with one result per line:

ok   github.com/example/project/internal/gatekeeper   0.574s   coverage: 100.0% of statements
ok   github.com/example/project/internal/webhook       0.593s   coverage: 97.7% of statements

Actual Behavior

Output is garbled — lines overlap and fuse together:

e: 100.0% of statementstekeeper     0.574s  coverage

When the agent runs $Host.UI.RawUI.WindowSize.Width inside the terminal, it reports 48 columns (at my preferred chat panel width). Any CLI output line exceeding this width is hard-wrapped by Windows ConPTY with an injected \r\n. When tools subsequently emit \r (carriage return for progress updates), the cursor returns to column 0 of the wrong row, causing text from different lines to overwrite each other.

Detailed anatomy of corruption

  1. go test prints: ok github.com/example/pkg/gatekeeper 0.574s (73 chars)
  2. ConPTY hard-wraps at column 48: row 1 gets ok github.com/example/pkg/ga, row 2 gets tekeeper 0.574s
  3. go test emits \r to update the line with coverage info
  4. \r moves cursor to column 0 of row 2 (the wrapped portion)
  5. go test prints coverage: 100.0% of statements (30 chars), overwriting only the first 30 chars of row 2
  6. Result: coverage: 100.0% of statementstekeeper 0.574s — a fused, corrupted line

Root Cause Analysis

The PTY cols dimension is dynamically derived from the chat panel’s rendered pixel width. Since the chat panel is typically in the sidebar, the resulting column count is very low (48-69 observed). This is inappropriate for a programmatic terminal — AI agents need to parse full-width CLI output, and the panel’s visual width is irrelevant since the agent reads text, not a visual terminal.

Setting environment variables (CI=true, TERM=dumb, NO_COLOR=1) mitigates progress-bar \r emissions from some tools but does not fix ConPTY hard-wrapping, which is caused by the narrow column count regardless of tool behavior.

Impact

  • Token waste: The agent frequently retries commands with workarounds (Select-String filters, -run flags to reduce output Volume), often 2-4x per command
  • Missed errors: Test failure details, coverage percentages, and error messages are truncated or garbled, causing the agent to miss critical information
  • Reduced autonomy: The agent cannot reliably run go test, golangci-lint, npm, or task runner commands without manual intervention

Proposed Fix

Set the PTY column width to a large fixed value (e.g., 4096) when spawning the agent terminal, regardless of the chat panel’s visual width. The agent reads raw text output — it does not need the PTY geometry to match a visible terminal emulator.

If the PTY is spawned via node-pty, this would be:

pty.spawn(shell, args, { cols: 4096, rows: 100 });

Alternatively, expose a user-configurable setting:

{
  "antigravity.agent.terminalColumns": 4096
}

Workarounds (current)

  1. Manually widen the chat panel to increase PTY columns (sacrifices editor screen space)
  2. Pipe output through filters (| Select-String "PASS|FAIL|coverage") to reduce line count
  3. Use MCP tools (e.g., Pare MCP) that return structured JSON via the MCP protocol, bypassing the PTY entirely
  4. Set env vars (CI=true, TERM=dumb) to suppress interactive progress indicators (partial fix only)