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
|
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 #1365 (draft OMP-specific integration): that PR's review thread and #591 both assume "mutate
event.input.command" is a working mechanism ("The extension handler modifiesevent.input.commandwithin thetool_call. The subsequent tool execution will then use the modified parameters." — #591 comment). It isn't, per the OMPExtensionAPItype contract (ToolCallEventResult.input,shared-events.d.ts) 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 feat(omp): add extension-based rewrite integration for Oh My Pi #1365/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, #1365, #1741