Skip to content

Wire tool_result feedback for multi-turn command execution#314

Open
ashishpatel26 wants to merge 2 commits into
microsoft:mainfrom
ashishpatel26:fix/issue-203-multi-turn-execution
Open

Wire tool_result feedback for multi-turn command execution#314
ashishpatel26 wants to merge 2 commits into
microsoft:mainfrom
ashishpatel26:fix/issue-203-multi-turn-execution

Conversation

@ashishpatel26

Copy link
Copy Markdown

Closes #203

Summary

  • ChoiceExecution gains session_id — the recommendation executor now knows which ACP session dispatched the Send action.
  • New capture_and_feed_output helper (coordinator.rs) — after a non-insert Send completes, waits 1.5 s for the command to finish, reads pane output (OSC 133 shell-integration marks first, falls back to last 30 buffer lines), and emits AppEvent::CommandOutputReady.
  • New AppEvent::CommandOutputReady variant (app.rs) — carries session_id, pane_id, command, and output.
  • New App::handle_command_output_ready handler — synthesizes a follow-up PromptSubmission with the command text and captured output, submits it via turn_submit_prompt, and forwards it over prompt_tx to the ACP client as the next user turn.

The agent now receives terminal output after each recommended command and can decide next steps: confirm success, diagnose errors, suggest corrections, or continue a multi-step plan.

Exclusions:

  • The autofix fallback path (session_id = None) is excluded from the loop.
  • Insert-only actions skip capture because no command was executed.

Test plan

  • All 904 existing tests still pass
  • New unit test command_output_ready_submits_follow_up_prompt verifies that CommandOutputReady forwards a PromptSubmission to prompt_tx containing the command + output text

When the planner agent sends a Send action and the coordinator executes
it in a terminal pane, the agent previously had no way to observe the
outcome. This meant every recommendation was a one-shot fire-and-forget
with no follow-up reasoning.

This commit closes the feedback loop:

- `ChoiceExecution` gains a `session_id` field so the recommendation
  executor knows which ACP session dispatched the choice.

- `execute_choice` passes `session_id` down and, after a non-insert
  Send action completes, calls the new `capture_and_feed_output` helper.

- `capture_and_feed_output` waits 1.5 s for the command to finish, reads
  the pane output (OSC 133 shell-integration marks when available,
  falling back to the last 30 buffer lines), and emits
  `AppEvent::CommandOutputReady`.

- `App::handle_command_output_ready` synthesizes a follow-up
  `PromptSubmission` carrying the command text and captured output,
  calls `turn_submit_prompt`, and forwards the submission over
  `prompt_tx` so the ACP client delivers it as the next user turn.

The agent now receives the terminal output after each recommended
command and can decide next steps: confirm success, diagnose errors,
suggest corrections, or continue a multi-step plan.

The autofix fallback path (`session_id = None`) is explicitly excluded
from the loop; the heavy send-and-capture path is skipped for insert-
only actions where no command was executed.

All 904 existing tests pass; one new test (`command_output_ready_submits
_follow_up_prompt`) documents and protects the behaviour.

Closes microsoft#203
Copilot AI review requested due to automatic review settings June 17, 2026 06:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR adds a multi-turn command execution feedback loop: after a Send action runs in a terminal pane, the coordinator captures recent terminal output and the app submits it back to the agent as a follow-up prompt.

Changes:

  • Extend ChoiceExecution to carry an optional ACP session_id and thread it into choice execution.
  • Capture terminal output after Send and emit a new AppEvent::CommandOutputReady.
  • Handle CommandOutputReady by synthesizing and submitting a follow-up prompt, with a new unit test validating the behavior.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
tools/wta/src/coordinator.rs Adds session-aware post-Send output capture and emits CommandOutputReady.
tools/wta/src/app/autofix.rs Sets session_id: None for the autofix fallback execution path.
tools/wta/src/app.rs Introduces CommandOutputReady, handles it by submitting a follow-up prompt, and adds a unit test.

Comment on lines +421 to +430
if let Some(sid) = session_id {
capture_and_feed_output(
sid,
parent,
input,
shell_mgr,
event_tx,
)
.await;
}
Comment thread tools/wta/src/app.rs
Comment on lines +7962 to +7963
let follow_up_text = format!(
"## Command Output\n\nThe command `{}` was executed in pane `{}`.\n\nHere is the terminal output:\n\n```\n{}\n```\n\nPlease review the output and continue helping the user. If the command succeeded, let me know. If there were any errors or unexpected results, please help diagnose and resolve them.",
Comment on lines +644 to +659
const MAX_CHARS: usize = 4000;

// Try shell-integration first (OSC 133 marks give us the exact last command+output).
if let Ok(value) = shell_mgr.wt_read_last_prompt(pane_id).await {
let has_marks = value
.get("has_marks")
.and_then(|v| v.as_bool())
.unwrap_or(false);
if has_marks {
if let Some(content) = value.get("content").and_then(|c| c.as_str()) {
if !content.is_empty() {
return Some(truncate_for_log(content, MAX_CHARS));
}
}
}
}
@github-actions

Copy link
Copy Markdown

@check-spelling-bot Report

⚠️ Dictionary not found

Problems were encountered retrieving check dictionaries (cspell:clojure/src/clojure.txt cspell:css/dict/css.txt cspell:cpp/src/lang-keywords.txt cspell:swift/src/swift.txt cspell:python/src/additional_words.txt cspell:node/dict/node.txt cspell:dart/src/dart.txt cspell:haskell/dict/haskell.txt cspell:lua/dict/lua.txt cspell:ruby/dict/ruby.txt cspell:svelte/dict/svelte.txt cspell:ada/dict/ada.txt cspell:k8s/dict/k8s.txt cspell:cpp/src/lang-jargon.txt cspell:golang/dict/go.txt cspell:gaming-terms/dict/gaming-terms.txt cspell:fullstack/dict/fullstack.txt cspell:public-licenses/src/generated/public-licenses.txt cspell:elixir/dict/elixir.txt cspell:cpp/src/stdlib-cmath.txt cspell:sql/src/tsql.txt cspell:php/dict/php.txt cspell:sql/src/sql.txt cspell:cpp/src/stdlib-cerrno.txt cspell:python/src/common/extra.txt cspell:cpp/src/compiler-gcc.txt cspell:cpp/src/people.txt cspell:scala/dict/scala.txt cspell:shell/dict/shell-all-words.txt cspell:java/src/java.txt cspell:redis/dict/redis.txt cspell:dotnet/dict/dotnet.txt cspell:latex/dict/latex.txt cspell:cpp/src/compiler-clang-attributes.txt cspell:docker/src/docker-words.txt cspell:python/src/python/python-lib.txt cspell:software-terms/dict/softwareTerms.txt cspell:rust/dict/rust.txt cspell:java/src/java-terms.txt cspell:r/src/r.txt cspell:python/src/python/python.txt cspell:software-terms/dict/webServices.txt cspell:monkeyc/src/monkeyc_keywords.txt cspell:cpp/src/ecosystem.txt cspell:cpp/src/compiler-msvc.txt cspell:typescript/dict/typescript.txt cspell:cpp/src/stdlib-cpp.txt cspell:django/dict/django.txt cspell:powershell/dict/powershell.txt cspell:npm/dict/npm.txt cspell:public-licenses/src/additional-licenses.txt cspell:cpp/src/template-strings.txt cspell:html/dict/html.txt cspell:cpp/src/stdlib-c.txt).

⚠️ For more information, see check-dictionary-not-found.

🔴 Please review

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

Unrecognized words (3)

remotesigned
segfaults
Subscribe'd

These words are not needed and should be removed allsigned Backgrounder CANTCALLOUT Ccc cplusplus ctl Debian dotnet drv endptr EOFs evt Fullwidth gitlab hdr idl IME inbox ININPUTSYNCCALL intelligentterminal Ioctl KVM lbl lld lsb NODEFAULT NONINFRINGEMENT notif oss outdir Podcast pri prioritization rcv segfault SND sourced SWP Tbl testname transitioning unk unparseable unregisters Virt VMs webpage websites WINVER xsi

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:ashishpatel26/intelligent-terminal.git repository
on the fix/issue-203-multi-turn-execution branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/cfb6f7e75bbfc89c71eaa30366d0c166f1bd9c8c/apply.pl' |
perl - 'https://github.com/microsoft/intelligent-terminal/actions/runs/27689732721/attempts/1' &&
git commit -m 'Update check-spelling metadata'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2064) from .github/actions/spelling/expect/alphabet.txt .github/actions/spelling/expect/expect.txt .github/actions/spelling/expect/web.txt and unrecognized words (3)

Dictionary Entries Covers Uniquely
cspell:csharp/csharp.txt 32 2 2
cspell:aws/aws.txt 232 2 2
cspell:fonts/fonts.txt 536 1 1

Consider adding to the extra_dictionaries array (in the .github/actions/spelling/config.json file):

    "cspell:csharp/csharp.txt",
    "cspell:aws/aws.txt",
    "cspell:fonts/fonts.txt",

To stop checking additional dictionaries, put (in the .github/actions/spelling/config.json file):

"check_extra_dictionaries": []

Forbidden patterns 🙅 (1)

In order to address this, you could change the content to not match the forbidden patterns (comments before forbidden patterns may help explain why they're forbidden), add patterns for acceptable instances, or adjust the forbidden patterns themselves.

These forbidden patterns matched content:

Should be reentrancy
[Rr]e[- ]entrancy
Errors and Warnings ❌ (2)

See the 📂 files view, the 📜action log, 👼 SARIF report, or 📝 job summary for details.

❌ Errors and Warnings Count
⚠️ check-dictionary-not-found 54
❌ forbidden-pattern 1

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

@ashishpatel26

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

1 similar comment
@ashishpatel26

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

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.

Multi-turn command execution

2 participants