Detect chevron-style interactive prompts and fix indefinite foreground hang on unrecognised prompts#313244
Conversation
There was a problem hiding this comment.
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
- 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>
|
/requires-eval-assessment terminalbench2 gpt-5.4,claude-opus-4.6,claude-opus-4.7 |
…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>
|
⏳ Queued vscode build for
|
|
🚀 Queued eval-assessment publish build for
|
|
🔬 Queued eval-assessment benchmark for
Results will be posted back here when the run completes. |
|
✅ Eval-assessment build published.
|
|
📊 Eval-assessment benchmark complete.
Analysis ResultsResolution Rate
Token Usage
Step Counts
|
|
📊 Eval-assessment benchmark complete.
Analysis ResultsResolution Rate
Token Usage
Step Counts
|
|
📊 Eval-assessment benchmark complete.
Analysis ResultsResolution Rate
Token Usage
Step Counts
|
Fixes #312576
Problem
When the agent runs a sync (foreground) command via
run_in_terminaland the command launches an interactive prompt from a library likeprompts(used by vitest),enquirer, orinquirer, the agent does not detect that input is required and the call hangs indefinitely.Why it hangs forever
The foreground
run_in_terminalpath races four candidates: process exit, continue-in-background, user-specified timeout (default: none), andonDidDetectInputNeeded. When the process is alive waiting for input:OutputMonitorpolling loop seesisActive === trueand only transitions to Idle ifdetectsInputRequiredPatternmatches the cursor line.Cancelled.Cancelleddoes not resolve any of the foreground race candidates. The process is still alive, no user timeout was specified, andonDidDetectInputNeededwas 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 canonicalprompts/enquirer/inquirerrendering 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
onDidDetectInputNeededbefore 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
isActivetruetruetruetruefalseTests
›,❯,▸,▶) preceded by?with and without trailing whitespace; ANSI escape-prefixed prompt lines; negatives for already-typed responses, chevrons without leading?, and mid-line?with chevrononDidDetectInputNeededfires when extended timeout expires with an active process