fix(hook): return revised input from Pi tool_call handler - #3453
fix(hook): return revised input from Pi tool_call handler#3453thinhngotony wants to merge 1 commit into
Conversation
The Pi/OMP tool_call dispatcher builds the args a tool actually
executes with from a separate copy of event.input; it only swaps in
a handler's RETURNED { input } (ToolCallEventResult). The Pi extension
mutated event.input.command in place and returned nothing, so
rtk rewrite's result was silently discarded and bash commands never
actually ran through rtk.
Return { input: { ...event.input, command: rewritten } } instead,
preserving the other BashToolInput fields via spread. Verified
end-to-end against a live OMP session: the executed shell command
changed from 'git status' to 'rtk git status', confirmed via rtk's
own history.db.
Adds a regression test asserting the plugin source returns the
revised input rather than mutating event.input in place, and updates
hooks/pi/README.md to describe the correct mechanism.
There was a problem hiding this comment.
Pull request overview
Fixes the Pi coding-agent hook integration so rtk rewrite results actually affect the executed bash tool call by returning a ToolCallEventResult with a revised input payload (instead of mutating event.input in place, which the dispatcher does not observe).
Changes:
- Update
hooks/pi/rtk.tstool_call handler toreturn { input: { ...event.input, command: rewritten } }when a rewrite applies. - Update
hooks/pi/README.mdto document the return-based mechanism (not mutate-in-place). - Add a regression test ensuring the shipped Pi plugin source returns revised input and does not rely on in-place mutation.
Review note (maintainability):
- The new regression test’s “no mutation” assertion is currently keyed to a single exact substring (
"event.input.command = rewritten"). This is easy to evade with whitespace changes (e.g.,event.input.command=rewritten) or slightly different assignment formatting; consider strengthening the check to reject both"event.input.command ="and"event.input.command=", and/or assert the presence of the intended spread-return pattern more explicitly.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/hooks/init.rs |
Adds a regression test to prevent reintroducing the “mutate input in place” bug in the shipped Pi plugin source. |
hooks/pi/rtk.ts |
Fixes the Pi tool_call handler to return revised { input } so the dispatcher uses the rewritten command. |
hooks/pi/README.md |
Updates documentation to match the dispatcher contract (ToolCallEventResult.input) and the fixed implementation. |
|
@aeppling @xavierpestel-ai Can you guys help me to review this? |
|
This is a no-op on pi. The dispatcher only ever reads
|
|
Thanks for the correction. You’re right about upstream Pi: This PR targets Oh My Pi, whose dispatcher appears to differ. In the OMP version tested, mutating I’ll also fix the misleading |
Summary
hooks/pi/rtk.ts, feat(hook): add pi support #1741, released in rtk 0.42) sortk rewriteresults actually take effect — today the extension never rewrites a single command.tool_calldispatcher builds the args a tool actually executes with from a separate copy ofevent.input; it only substitutes a handler's returned{ input }(ToolCallEventResult). The handler mutatedevent.input.commandin place and returned nothing, so the rewrite was silently discarded on every call.return { input: { ...event.input, command: rewritten } }instead of mutating, preserving the otherBashToolInputfields via spread.hooks/pi/README.md's "Specifics" section, which documented the broken mutate-in-place mechanism as the intended design.test_pi_plugin_returns_revised_input_instead_of_mutating_in_place) asserting the shipped plugin source returns the revision and does not rely on mutatingevent.inputin place.Why this matters
This is the same file discussed in the Oh My Pi integration and rtk#591. That integration's review discussion assumed "mutate
event.input.command" was a working mechanism. It isn't in the affected OMP runtime, per itsExtensionAPIbehavior and confirmed empirically: after applying this exact fix locally and running a realomp -p --auto-approve "git status"session,rtk's ownhistory.dbrecordedgit status → rtk git status; before the fix, nothing was ever rewritten despite the extension loading and probing successfully.Test plan
cargo fmt --all -- --checkcargo clippy --all-targetscargo test(2563 passed, 0 failed, incl. new regression test)bun --eval 'await import("./hooks/pi/rtk.ts")'ompsession (Oh My Pi, the extension consumer for Add support for Oh-My-Pi #591), installed this exact fixed source as itstool_callhandler, rangit statusthrough the agent's bash tool.rtk's local history.db recorded the command asoriginal_cmd: git status,rtk_cmd: rtk git status— confirming the executed shell command was rewritten, not just displayed.Related: #401, #591, #1741