fix(openclaw): handle exit code 3 from rtk rewrite#2202
Conversation
KuSh
left a comment
There was a problem hiding this comment.
Thanks for your PR! While your current solution works as a temporary workaround, it’s not yet production-ready. I’ve left some suggestions to help guide you toward a more robust, final implementation.
Let me know if you’d like further clarification or assistance!
Address KuSh review feedback on rtk-ai#2202: - tryRewrite now returns [string | null, "ask"?] tuple - Exit code 3 specifically checked (e.status === 3) - before_tool_call returns requireApproval when rewrite is a suggestion (exit 3), per OpenClaw hook docs - 60s approval timeout with deny on timeout See: rtk-ai#2202 (review) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
Address KuSh review feedback on rtk-ai#2202: - tryRewrite now returns [string | null, "ask"?] tuple - Exit code 3 specifically checked (e.status === 3) - before_tool_call returns requireApproval when rewrite is a suggestion (exit 3), per OpenClaw hook docs - 60s approval timeout with deny on timeout See: rtk-ai#2202 (review) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
1162f2d to
2256da9
Compare
Rework the plugin to respect RTK's full exit code protocol (src/hooks/rewrite_cmd.rs): Exit codes: 0 + stdout Allow — auto-apply rewrite (no approval) 1 No match — pass through unchanged 2 Deny — block the call (new) 3 + stdout Ask — rewrite with requireApproval (KuSh review) Changes: - tryRewrite returns [string | null, "ask" | "deny" | undefined] - Exit 3: requireApproval with configurable timeout (default 120s) - Exit 2: block:true (was silently passed through — security gap) - allowedDecisions: ["allow-once", "deny"] — no allow-always (plugin does not persist trust) - onResolution callback for verbose logging - approvalTimeoutMs config option in openclaw.plugin.json - Documented exit code protocol in file header Address KuSh review: rtk-ai#2202 (review) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
KuSh
left a comment
There was a problem hiding this comment.
Just a few remaining nitpicks and questions
…t timeoutMs - Extract RewriteVerdict type per KuSh suggestion - Remove timeoutMs from requireApproval (omit to use Gateway default) - Remove approvalTimeoutMs config option from plugin.json - allowedDecisions still excludes allow-always: OpenClaw docs confirm plugin allow-always does not auto-persist; offering it without our own persistence would mislead users Address KuSh review: rtk-ai#2202 (review-4588193872) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
|
Thanks for the thorough review, KuSh — really appreciate the guidance. 1. 2. 3.
The troubleshooting section reinforces this:
Since this plugin doesn't implement its own trust persistence, offering |
9827755 to
6b2851c
Compare
Address KuSh review feedback on rtk-ai#2202: - tryRewrite now returns [string | null, "ask"?] tuple - Exit code 3 specifically checked (e.status === 3) - before_tool_call returns requireApproval when rewrite is a suggestion (exit 3), per OpenClaw hook docs - 60s approval timeout with deny on timeout See: rtk-ai#2202 (review) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
Rework the plugin to respect RTK's full exit code protocol (src/hooks/rewrite_cmd.rs): Exit codes: 0 + stdout Allow — auto-apply rewrite (no approval) 1 No match — pass through unchanged 2 Deny — block the call (new) 3 + stdout Ask — rewrite with requireApproval (KuSh review) Changes: - tryRewrite returns [string | null, "ask" | "deny" | undefined] - Exit 3: requireApproval with configurable timeout (default 120s) - Exit 2: block:true (was silently passed through — security gap) - allowedDecisions: ["allow-once", "deny"] — no allow-always (plugin does not persist trust) - onResolution callback for verbose logging - approvalTimeoutMs config option in openclaw.plugin.json - Documented exit code protocol in file header Address KuSh review: rtk-ai#2202 (review) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
…t timeoutMs - Extract RewriteVerdict type per KuSh suggestion - Remove timeoutMs from requireApproval (omit to use Gateway default) - Remove approvalTimeoutMs config option from plugin.json - allowedDecisions still excludes allow-always: OpenClaw docs confirm plugin allow-always does not auto-persist; offering it without our own persistence would mislead users Address KuSh review: rtk-ai#2202 (review-4588193872) Signed-off-by: Karol Zalewski <karol.zalewski@4zal.net>
6b2851c to
c059525
Compare
f5c6eab to
97aaac8
Compare
0d50a72 to
8b632e9
Compare
Interpret all RTK rewrite exit codes and respond appropriately: - Exit 0 (Allow): auto-apply rewrite - Exit 1 (Passthrough): no RTK equivalent, pass through unchanged - Exit 2 (Deny): block the call entirely - Exit 3 (Ask): rewrite available, require user approval via requireApproval with allow-once/deny decisions Uses execFileSync (not execSync) to avoid shell injection. Returns a [string | null, RewriteVerdict?] tuple from tryRewrite so the before_tool_call hook can react to each verdict type. "allow-always" omitted from allowedDecisions because OpenClaw does not auto-persist approval for plugin hooks — see: https://docs.openclaw.ai/plugins/plugin-permission-requests#troubleshooting Closes rtk-ai#2202
8b632e9 to
776a4b1
Compare
|
Thanks KuSh! All three rounds of feedback are now addressed in a single squashed commit (776a4b1):
|
KuSh
left a comment
There was a problem hiding this comment.
LGTM, thanks for keeping up!
Problem
The rtk-rewrite OpenClaw plugin silently drops all command rewrites. Every
rtk rewritecall that produces a suggestion returns exit code 3, whichexecSynctreats as an exception. The catch block returnsnull, so no command is ever rewritten.See #2200 for full analysis.
Fix
Check
e.stdoutin the catch handler — exit code 3 with stdout output is a valid rewrite suggestion, not an error:Verified
All common shell commands now correctly rewritten:
All previously returned
null(no rewrite) with the upstream code.Aiko — AI assistant in OpenClaw
Running RTK on k3s with Kilo Gateway
Config: RTK 0.42.0 | OpenClaw 2026.5.28 | Node.js v24.14.0 | Model: MiMo-V2.5-Pro
Reviewed and verified by Zal (@kzzalews)