Add output truncation for large command results to preserve AI context window#34
Add output truncation for large command results to preserve AI context window#34doraemonkeys wants to merge 4 commits intoyotsuda:mainfrom
Conversation
- Introduced OutputTruncationHelper class to truncate large outputs, saving full content to a temporary file for retrieval. - Updated PowerShellTools to utilize OutputTruncationHelper for response handling, ensuring outputs are truncated when exceeding the defined threshold. - Added unit tests for OutputTruncationHelper to validate functionality, including edge cases for output size and file saving.
|
Thank you for this well-designed PR! The code quality is high — clean implementation, proper error handling with graceful degradation, newline-aligned boundaries, and comprehensive tests. All 216 tests pass (including the 17 new ones). However, I have an architectural concern about where the truncation happens. Truncation should happen in the DLL module, not the ProxyCurrently, the truncation logic lives in graph TD
A["PowerShell (command execution)"] -->|"full output"| B["PowerShell.MCP dll module"]
B -->|"⚠️ full output still flows through named pipe"| C["MCP Server (proxy exe)<br/>★ truncation + file save happens here"]
C -->|"preview only"| D["AI client"]
style C fill:#fee,stroke:#c00,color:#900
The truncation should instead happen in the DLL module, right after the pipeline execution completes. This way:
Truncation threshold is too lowThe current The Looking forward to a revised version! |
… DLL module Truncation now happens in PowerShellCommunication.NotifyResultReady() before caching, so only the truncated preview crosses the named pipe — reducing pipe transfer size and memory overhead. Full output is saved to a temp file on the DLL side. - Add PowerShell.MCP.Shared project with OutputTruncationHelper (threshold 15K) - Remove OutputTruncationHelper from Proxy/Helpers (no longer needed there) - Add NotifySilentResultReady() for small known-output internal paths - Update project references and solution file - Move tests to Tests/Unit/Shared/
|
Thanks for the review! All three concerns have been addressed:
The Claude Code Bash tool's 30K threshold (~7.5K tokens) is ~3.75% of a 200K context window. A single call is fine, but users often execute multiple commands in succession. If each returns close to the threshold, context consumption adds up quickly. I believe 15K already strikes a good balance between usability and context efficiency. |
|
@doraemonkeys Thank you for this contribution! The feature itself is very useful — truncating large outputs to preserve the AI context window is exactly the right approach, and the "preview + file fallback" pattern inspired by Claude Code's Bash tool is a great design choice. I have some feedback before we can merge this. Architecture: Remove PowerShell.MCP.Shared, keep changes in the DLL onlyThe main feedback is about where truncation is applied. Currently the PR:
This can be simplified significantly. Looking at the output flow: flowchart LR
A["PowerShell<br/>execution result"] --> B["NotifyResultReady()<br/>☑ truncate here"]
B --> C["ExecutionState<br/>cache"]
C --> D[Named Pipe]
D --> E["PowerShellTools<br/>✗ no changes needed"]
style B fill:#d4edda,stroke:#28a745,color:#155724
style E fill:#f8d7da,stroke:#dc3545,color:#721c24
If truncation happens in
This reduces the diff substantially and keeps the Proxy untouched. Other items
|
Truncation in NotifyResultReady() means the Proxy already receives truncated output, so the 12 TruncateIfNeeded calls on the Proxy side and the Shared project are unnecessary. - Move OutputTruncationHelper into PowerShell.MCP (DLL project) - Remove all TruncateIfNeeded calls from PowerShellTools.cs - Remove PowerShell.MCP.Shared project and all references - Fix truncation message: Get-Content → Show-TextFiles (avoids re-truncation loop) - Strengthen newline alignment test assertions to verify actual boundary positions instead of vacuously passing on metadata newlines
Removed PowerShell.MCP.Shared — OutputTruncationHelper now lives directly in the DLL project Removed all 12 TruncateIfNeeded calls from Proxy — since NotifyResultReady() already truncates before caching, the Proxy receives pre-truncated output Removed InternalsVisibleTo from Proxy .csproj — no longer needed Fixed truncation message — replaced Get-Content / Read tool with Show-TextFiles -Contains to avoid the re-truncation loop Strengthened newline alignment tests — assertions now verify actual boundary positions instead of passing vacuously on metadata newlines |
Summary
Adds
OutputTruncationHelperto automatically truncate large command outputs, preserving AI context window budget.The design is inspired by Claude Code's Bash tool truncation mechanism — when Bash output exceeds the size limit,
Claude Code saves the full content to a temp file and returns a head preview with the file path, allowing the AI to
retrieve the full output via the Read tool when needed. We adopt the same pattern for PowerShell.MCP's
invoke_expressionresponses.Changes
OutputTruncationHelperthat truncates outputs exceeding 5,000 charactersreturned with the file path for retrieval via
Get-Contentor the Read tooloverlapping head/tail content
PowerShellTools(12 call sites)InternalsVisibleTofor the test projectdegradation on disk failure, and temp file cleanup
Design rationale
Claude Code's Bash tool handles large outputs by saving the full content to a file and returning a truncated preview
with the file path. Without similar handling, PowerShell.MCP
would return unbounded output directly into the AI's context window, wasting tokens and potentially hitting context
limits. This PR brings the same "preview + file fallback" pattern to all PowerShell tool responses.