outputMonitor: fix two false-positive families pausing the agent loop#315485
Merged
meganrogge merged 1 commit intoMay 11, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR refines the terminal OutputMonitor input-needed heuristics used by the chat agent terminal tooling to reduce false positives that pause the agent loop on benign output (e.g., log lines ending in : / ? and git-aware shell prompts like git:(main)).
Changes:
- Split “input-needed” detection into a strict path (
detectsInputRequiredPattern→ high-confidence only) and a broader, gated path (detectsLikelyInputRequiredPattern). - Tighten the parenthesized-default regex to avoid matching oh-my-zsh / git-aware prompts (
:\s*→:\s+). - Expand unit/integration-style tests to cover the reported false-positive families and regressions.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/vs/workbench/contrib/terminalContrib/chatAgentTools/browser/tools/monitoring/outputMonitor.ts |
Splits strict vs broad prompt detection, updates idle polling gating, and tightens the parenthesized-default regex. |
src/vs/workbench/contrib/terminalContrib/chatAgentTools/test/browser/outputMonitor.test.ts |
Adds regressions and new suites validating strict vs likely behavior and prompt false-positive avoidance. |
c198177 to
1367c62
Compare
1367c62 to
e712877
Compare
e712877 to
0aae89a
Compare
Fixes microsoft#315476. This change addresses two related false-positive families in RunInTerminalTool's input-needed heuristic that pause the agent loop on benign terminal output. ### Family 1 — ``'s broad fallback regexes match log output `detectsInputRequiredPattern` ($Ri minified) augmented `Vyo`'s strict pattern set with two over-broad fallbacks: /: +$/ (any line ending colon + spaces) /\? *(?:\([a-z\s]+\))? +$/i (any line ending question + spaces) These fire on log output like: [INFO] Starting: Last Command: find: /tmp/x: No such file: Are you sure you want to do this? (rhetorical) The strict guard at the call site is shell-integration's `isActive` flag, which is only true when the foreground process is actively holding stdin open. `_handleIdleState` (line ~388/408) was using the broad pattern unconditionally, with no isActive evidence. Fix: split the function into two: - detectsInputRequiredPattern(line): strict-only — delegates to detectsHighConfidenceInputPattern. Safe to call from any path, including unconditionally on the last line of a finished command. - detectsLikelyInputRequiredPattern(line): strict + broad fallbacks. Should only be called when an out-of-band signal already confirms the process is awaiting input (isActive === true). Update the callers: - _handleIdleState (lines ~388, ~408): switch to the strict detectsInputRequiredPattern. Eliminates the log-line false positives that were pausing the agent. - _waitForIdle (line ~532): keep using the broad detectsLikelyInputRequiredPattern. This call is gated by `recentlyIdle && isActive === true`, which provides the out-of-band evidence the broad fallbacks need. ### Family 2 — `Vyo`'s paren-default rule matches every oh-my-zsh prompt `Vyo` (detectsHighConfidenceInputPattern) contained a rule: /:\s*\([^)]*\) +$/ // "package name: (test) " intended for npm-init / yarn-init style prompts. Because `\s*` allows zero spaces between `:` and `(`, this also matches every git-aware shell prompt: ➜ myrepo git:(main) ➜ vscode git:(ba-work/output-monitor) (oh-my-zsh's robbyrussell theme; bash with __git_ps1; etc.) Live trigger rate: every shell-prompt return, on every benign command, on every machine running oh-my-zsh. The agent loop pauses for ~2 minutes (the _handleTimeoutState recovery window) before resuming on every command, making multi-step tasks unusable. Fix: tighten `\s*` -> `\s+` so at least one space is required between `:` and `(`. npm-init prompts always render a space ("name: (default)"); shell-prompt PS1 themes never do ("git:(main)"). Single-byte regex change, no behavioural change to the npm-init / yarn-init matches. ### Tests - Update test 'Line ends with colon (strict path)' to assert that bare "Enter your name: ", "File to overwrite: ", and log lines like "Last Command: ", "[INFO] Starting: ", "find: /tmp/x: No such file: ", "error: subprocess returned: ", and "2025-05-09 12:34:56 INFO Starting: " all return FALSE under the strict detectsInputRequiredPattern. - Update test 'detects trailing questions (strict path does not match bare ? prompts)' similarly. - Add new suite for detectsLikelyInputRequiredPattern with parity tests, bare-colon/question matching, non-prompt rejection, and documented false positives (e.g. log lines with colons). - Add regression cases in detectsHighConfidenceInputPattern asserting that oh-my-zsh / git-aware prompts return FALSE while npm-init prompts continue to return TRUE. - Add regression cases in detectsInputRequiredPattern (strict) and detectsLikelyInputRequiredPattern asserting the same for the oh-my-zsh case (since the strict rule flows through both paths). ### How to verify Reproduce in the integrated terminal with shell integration enabled on a machine using oh-my-zsh's robbyrussell theme: cd ~/anywhere && git status Without the fix: agent pauses for ~2 minutes after the command returns. With the fix: agent continues immediately.
0aae89a to
14ba5fb
Compare
Collaborator
|
Good catch on |
aeschli
approved these changes
May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #315476.
This change addresses two related false-positive families in
RunInTerminalTool's input-needed heuristic that pause the agent loop on benign terminal output. Both surfaced live: the$Rifamily on log lines ending in:or?, and theVyofamily on every command return when the shell uses an oh-my-zsh-style git-aware PS1 prompt.Family 1 —
detectsInputRequiredPattern's broad fallbacks match log outputdetectsInputRequiredPatternaugmenteddetectsHighConfidenceInputPattern's strict pattern set with two over-broad fallbacks:These fire on benign log output like:
The strict guard at the original call site is shell-integration's
isActiveflag, which is only true when the foreground process is actively holding stdin open._handleIdleStatewas using the broad pattern unconditionally, with noisActiveevidence.Fix: split the function into two:
detectsInputRequiredPattern(line): strict-only — delegates todetectsHighConfidenceInputPattern. Safe to call from any path, including unconditionally on the last line of a finished command.detectsLikelyInputRequiredPattern(line): strict + broad fallbacks. Should only be called when an out-of-band signal already confirms the process is awaiting input (isActive === true).Update the callers:
_handleIdleState: switch to the strictdetectsInputRequiredPattern. Eliminates the log-line false positives._waitForIdle: keep using the broaddetectsLikelyInputRequiredPattern. This call is gated byrecentlyIdle && isActive === true, which provides the out-of-band evidence the broad fallbacks need.Family 2 —
detectsHighConfidenceInputPattern's paren-default rule matches every oh-my-zsh promptdetectsHighConfidenceInputPatterncontained this rule:intended for npm-init / yarn-init style prompts. Because
\s*allows zero spaces between:and(, it also matches every git-aware shell prompt:(oh-my-zsh's
robbyrusselltheme; bash with__git_ps1; etc.) Live trigger rate: every shell-prompt return, on every benign command, on every machine running oh-my-zsh. The agent loop pauses for ~2 minutes (the_handleTimeoutStaterecovery window) before resuming on every command, making multi-step tasks unusable.Fix: tighten
\s*→\s+so at least one space is required between:and(. npm-init prompts always render a space (name: (default)); shell-prompt PS1 themes never do (git:(main)). Single-byte regex change, no behavioural change to the npm-init / yarn-init matches.Tests
Line ends with colonto use the strict path and assert that bareEnter your name:,File to overwrite:, and log lines likeLast Command:,[INFO] Starting:,find: /tmp/x: No such file:,error: subprocess returned:, and2025-05-09 12:34:56 INFO Starting:all returnfalseunder the strictdetectsInputRequiredPattern.detects trailing questionssimilarly.detectsLikelyInputRequiredPatterncovering strict-set parity, bare-colon/question matching, non-prompt rejection, and the documented false positives (log lines with colons) so the broad surface stays understood.detectsHighConfidenceInputPatternasserting that oh-my-zsh / git-aware prompts returnfalsewhile npm-init prompts continue to returntrue.detectsInputRequiredPattern(strict) anddetectsLikelyInputRequiredPatternso the rule's flow through both call paths is pinned.OutputMonitorintegration tests assertingonDidDetectInputNeededdoes NOT fire for (a) log lines ending in:, (b) lines ending in?, (c) oh-my-zsh git-aware shell prompts. These pin the wiring at_handleIdleState, not just the regex behaviour in isolation.How to verify
Family 2 (oh-my-zsh prompts): in the integrated terminal with shell integration enabled, on a machine using oh-my-zsh's
robbyrusselltheme (or any git-aware PS1 that rendersgit:(branch)with no space after the colon), run any command from agent mode that returns to the prompt:Without the fix: the agent pauses for ~2 minutes after every command return. With the fix: the agent continues immediately.
Family 1 (broad-fallback log lines): from agent mode, run a slow-ish command whose visible buffer ends in
:while the command is still being polled (the strict path is what firesonDidDetectInputNeeded; running command output, not the post-prompt return, is what_handleIdleStateevaluates):Without the fix: the agent pauses with the input-needed wrapper because
detectsInputRequiredPattern's broad/: +$/fallback matches the trailing:. With the fix:_handleIdleStatecalls the strict path, which no longer carries those fallbacks, and the wrapper does not fire.Scope
This PR is intentionally limited to the two false-positive families called out in #315476. While reading the surrounding code I noticed
detectsGenericPressAnyKeyPatternis invoked withoutputTailrather thanoutputLastLine(line ~370), which is inconsistent with sibling line-oriented detectors. That predates this PR and is out of scope here; happy to file a separate fix if a maintainer agrees it's worth addressing.