Skip to content

Detect chevron-style interactive prompts and fix indefinite foreground hang on unrecognised prompts#313244

Merged
meganrogge merged 6 commits into
mainfrom
megan/fix-312576-chevron-prompt-detection
Apr 29, 2026
Merged

Detect chevron-style interactive prompts and fix indefinite foreground hang on unrecognised prompts#313244
meganrogge merged 6 commits into
mainfrom
megan/fix-312576-chevron-prompt-detection

Conversation

@meganrogge
Copy link
Copy Markdown
Collaborator

@meganrogge meganrogge commented Apr 29, 2026

Fixes #312576

Problem

When the agent runs a sync (foreground) command via run_in_terminal and the command launches an interactive prompt from a library like prompts (used by vitest), enquirer, or inquirer, the agent does not detect that input is required and the call hangs indefinitely.

Why it hangs forever

The foreground run_in_terminal path races four candidates: process exit, continue-in-background, user-specified timeout (default: none), and onDidDetectInputNeeded. When the process is alive waiting for input:

  1. The OutputMonitor polling loop sees isActive === true and only transitions to Idle if detectsInputRequiredPattern matches the cursor line.
  2. Without a matching pattern, the monitor keeps polling until its internal 2-minute extended timeout, then sets state to Cancelled.
  3. But Cancelled does not resolve any of the foreground race candidates. The process is still alive, no user timeout was specified, and onDidDetectInputNeeded was never fired — so the race hangs forever.

Fix

1. Chevron prompt pattern

Add a new pattern in detectsHighConfidenceInputPattern (the fast-path checked on every poll tick) that matches lines starting with ? (after optional whitespace/ANSI escapes) and ending with a prompt-library chevron glyph ( U+203A, U+276F, U+25B8, U+25B6). Anchoring ? to the start of the line matches the canonical prompts/enquirer/inquirer rendering and avoids false positives from incidental ? + chevron combinations in normal output (e.g. What happened? ›).

2. Extended timeout safety net

When the 2-minute extended polling timeout fires, fire onDidDetectInputNeeded before cancelling. This is the critical fix for the indefinite hang — it resolves the foreground race so the agent receives the terminal output and can assess/respond.

3. Soften notification language

Changed the background steering message from "command is waiting for input" to "command may be waiting for input", and the UI label from "needs input" to "may need input". This is important because the event now also fires on extended timeout where the process might just be slow rather than actually waiting for input. The steering text already instructs the agent to assess the output before acting.

Decision matrix: extended timeout behavior

Scenario isActive Without firing event With firing event
Unrecognised prompt (fg) true ❌ Hangs forever — no race candidate resolves ✅ Agent gets output, can assess and respond
Unrecognised prompt (bg) true ❌ Silently cancelled, agent never sees it ✅ Steering message sent, agent assesses output
Long-running command (fg) — e.g. 3min build true ⚠️ Also hangs forever (same bug, different cause) ✅ Agent told "may need input" — steering text says "call GetTerminalOutput to continue polling", so agent polls and build finishes normally
Long-running command (bg) true Silent cancel at 2min ⚠️ Benign steering message — agent sees output, assesses "still running", continues polling
Already exited process false N/A — caught before timeout Same

Tests

  • Chevron pattern tests: each chevron variant (, , , ) preceded by ? with and without trailing whitespace; ANSI escape-prefixed prompt lines; negatives for already-typed responses, chevrons without leading ?, and mid-line ? with chevron
  • Extended timeout test: verifies onDidDetectInputNeeded fires when extended timeout expires with an active process

Copilot AI review requested due to automatic review settings April 29, 2026 14:41
@meganrogge meganrogge self-assigned this Apr 29, 2026
@meganrogge meganrogge added this to the 1.119.0 milestone Apr 29, 2026
@meganrogge meganrogge enabled auto-merge (squash) April 29, 2026 14:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves terminal run_in_terminal prompt detection so agent executions don’t hang indefinitely when common Node prompt libraries (eg prompts/enquirer/inquirer) render interactive questions that end with chevron-style glyphs.

Changes:

  • Added a chevron-glyph input detection regex intended to recognize ? ... <chevron> prompt lines.
  • Added unit tests covering multiple chevron variants and basic positive/negative cases.
Show a summary per file
File Description
src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/monitoring/outputMonitor.ts Adds a chevron-based regex to the input-needed detection patterns.
src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/outputMonitor.test.ts Adds tests for chevron-style interactive prompts and a few negative cases.

Copilot's findings

Comments suppressed due to low confidence (1)

src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/monitoring/outputMonitor.ts:616

  • The new chevron prompt regex (/\?.*[›❯▸▶]\s*$/) only requires a ? anywhere on the line, but the comment/PR description says these libraries prefix prompts with ? (at the start). As written, a non-prompt line like "What happened? ›" would be treated as input-required if it happens to end with one of these glyphs. Consider tightening the pattern to require the canonical prompt prefix (e.g. start-of-line ? + whitespace) so it matches the intended rendering and reduces false positives.
		// Interactive prompt libraries (prompts, enquirer, inquirer) prefix the prompt with
		// '? ' and end the line with a distinctive chevron character followed by optional
		// trailing whitespace where the cursor is awaiting input. Requiring a '?' earlier
		// on the line avoids false positives from random output that happens to contain a
		// chevron (e.g. git log decorations).
		// Examples:
		//   "? Do you want to install jsdom? <chevron>"  (prompts)
		//   "? Pick a color <chevron> "                  (inquirer / enquirer)
		// allow-any-unicode-next-line
		/\?.*[›❯▸▶]\s*$/,
  • Files reviewed: 2/2 changed files
  • Comments generated: 2

meganrogge and others added 2 commits April 29, 2026 10:58
- Anchor the ? to start-of-line (with optional whitespace/ANSI escapes)
  to avoid false positives like "What happened? ›"
- Add negative test for mid-line ? with chevron
- Add positive test for ANSI-prefixed prompt lines
- Update comment to reflect the tightened pattern

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the 2-minute extended polling timeout fires and the process is
still active, fire onDidDetectInputNeeded instead of silently cancelling.
This ensures the agent sees the terminal output and can assess/respond
to unrecognised interactive prompts rather than hanging indefinitely.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@meganrogge meganrogge changed the title Detect chevron-style interactive prompts in agent terminal Detect chevron-style interactive prompts and fix indefinite foreground hang on unrecognised prompts Apr 29, 2026
@meganrogge
Copy link
Copy Markdown
Collaborator Author

/requires-eval-assessment terminalbench2 gpt-5.4,claude-opus-4.6,claude-opus-4.7

@meganrogge meganrogge requested a review from Copilot April 29, 2026 15:19
@vs-code-engineering vs-code-engineering Bot added the ~requires-eval-assessment Evals will be run and will generate a report upon completion label Apr 29, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 2

meganrogge and others added 3 commits April 29, 2026 11:36
…r/tools/monitoring/outputMonitor.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…s/browser/tools/monitoring/outputMonitor.ts"

This reverts commit 93761d6.
The background steering message and UI label now say "may be waiting
for input" / "may need input" instead of asserting input is definitely
needed.  This is important because onDidDetectInputNeeded also fires
on extended timeout where the process might just be slow rather than
waiting for input.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@meganrogge meganrogge added ~requires-eval-assessment Evals will be run and will generate a report upon completion and removed ~requires-eval-assessment Evals will be run and will generate a report upon completion labels Apr 29, 2026
@vs-code-engineering
Copy link
Copy Markdown
Contributor

⏳ Queued vscode build for 62f020120ff3b0d304296ef6f0f517af7c1a00f1 (step 1/2).

@meganrogge meganrogge merged commit 6707517 into main Apr 29, 2026
26 checks passed
@meganrogge meganrogge deleted the megan/fix-312576-chevron-prompt-detection branch April 29, 2026 16:04
@vs-code-engineering
Copy link
Copy Markdown
Contributor

🚀 Queued eval-assessment publish build for a6951e11ba48bf63fc669ea802ca431ed9565753 (step 2/2).

@vs-code-engineering
Copy link
Copy Markdown
Contributor

🔬 Queued eval-assessment benchmark for 8fec77ac24.

Results will be posted back here when the run completes.

@vs-code-engineering
Copy link
Copy Markdown
Contributor

✅ Eval-assessment build published.

@vs-code-engineering vs-code-engineering Bot removed the ~requires-eval-assessment Evals will be run and will generate a report upon completion label Apr 29, 2026
@vs-code-engineering
Copy link
Copy Markdown
Contributor

📊 Eval-assessment benchmark complete.

Analysis Results

Resolution Rate

Benchmark Total Cases Passed Failed Resolved Rate
terminalbench2 89 70 19 78.65%

Token Usage

Metric Value
Total Tokens 74,858,135
Input Tokens 73,733,364
Output Tokens 1,124,771
Cached Tokens 70,833,033

Step Counts

Metric Value
Total Steps 1,877
Mean Steps/Instance 21.09

@vs-code-engineering
Copy link
Copy Markdown
Contributor

📊 Eval-assessment benchmark complete.

Analysis Results

Resolution Rate

Benchmark Total Cases Passed Failed Resolved Rate
terminalbench2 89 49 40 55.06%

Token Usage

Metric Value
Total Tokens 51,208,362
Input Tokens 50,198,448
Output Tokens 1,009,914
Cached Tokens 47,123,467

Step Counts

Metric Value
Total Steps 1,822
Mean Steps/Instance 20.47

@vs-code-engineering
Copy link
Copy Markdown
Contributor

📊 Eval-assessment benchmark complete.

Analysis Results

Resolution Rate

Benchmark Total Cases Passed Failed Resolved Rate
terminalbench2 89 45 44 50.56%

Token Usage

Metric Value
Total Tokens 72,042,918
Input Tokens 71,131,026
Output Tokens 911,892
Cached Tokens 61,496,960

Step Counts

Metric Value
Total Steps 1,566
Mean Steps/Instance 17.60

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Terminal stuck forever on sync command

3 participants