Skip to content

Commit 884648d

Browse files
committed
Merge PR warpdotdev#35: PostToolUse hook perf optimization (~200ms → <30ms)
2 parents af2ae6b + f219c64 commit 884648d

2 files changed

Lines changed: 94 additions & 9 deletions

File tree

plugins/warp/scripts/on-post-tool-use.sh

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,26 @@
33
# Sends a structured Warp notification after a tool call completes,
44
# transitioning the session status from Blocked back to Running.
55

6+
[ -z "${WARP_CLI_AGENT_PROTOCOL_VERSION:-}" ] && exit 0
7+
68
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
79
source "$SCRIPT_DIR/should-use-structured.sh"
810

9-
# No legacy equivalent for this hook
1011
if ! should_use_structured; then
1112
exit 0
1213
fi
1314

14-
source "$SCRIPT_DIR/build-payload.sh"
15-
16-
# Read hook input from stdin
17-
INPUT=$(cat)
15+
PROTOCOL_VERSION="${WARP_CLI_AGENT_PROTOCOL_VERSION:-1}"
16+
[[ "$PROTOCOL_VERSION" =~ ^[0-9]+$ ]] || PROTOCOL_VERSION=1
17+
[ "$PROTOCOL_VERSION" -gt 1 ] && PROTOCOL_VERSION=1
1818

19-
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null)
19+
BODY=$(jq -nc \
20+
--argjson v "$PROTOCOL_VERSION" \
21+
--arg agent "claude" \
22+
--arg event "tool_complete" \
23+
'{v:$v, agent:$agent, event:$event}
24+
+ (input | {session_id: (.session_id // ""), cwd: (.cwd // ""), project: ((.cwd // "") | sub("/+$"; "") | sub(".*/"; "")), tool_name: (.tool_name // "")})' 2>/dev/null) || exit 0
2025

21-
BODY=$(build_payload "$INPUT" "tool_complete" \
22-
--arg tool_name "$TOOL_NAME")
26+
[ -z "$BODY" ] && exit 0
2327

24-
"$SCRIPT_DIR/warp-notify.sh" "warp://cli-agent" "$BODY"
28+
printf '\033]777;notify;%s;%s\007' "warp://cli-agent" "$BODY" > /dev/tty 2>/dev/null &

plugins/warp/tests/test-hooks.sh

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,87 @@ for HOOK in on-permission-request.sh on-prompt-submit.sh on-post-tool-use.sh; do
223223
assert_eq "$HOOK exits 0 without protocol version" "0" "$?"
224224
done
225225

226+
# --- PostToolUse payload tests ---
227+
# The optimized on-post-tool-use.sh inlines payload construction and writes
228+
# to /dev/tty. We use `script` to capture pty output and extract the JSON.
229+
230+
run_hook_capture() {
231+
local hook="$1"
232+
local input="$2"
233+
local tmpfile inputfile
234+
tmpfile=$(mktemp)
235+
inputfile=$(mktemp)
236+
printf '%s' "$input" > "$inputfile"
237+
script -q "$tmpfile" bash -c "bash \"$HOOK_DIR/$hook\" < \"$inputfile\"; wait; sleep 0.2" >/dev/null 2>&1
238+
local payload
239+
payload=$(tr -d '\r' < "$tmpfile" | grep -o '{[^}]*}' | tail -1)
240+
rm -f "$tmpfile" "$inputfile"
241+
echo "$payload"
242+
}
243+
244+
echo ""
245+
echo "=== on-post-tool-use.sh (payload) ==="
246+
247+
echo ""
248+
echo "--- Basic payload construction ---"
249+
export WARP_CLI_AGENT_PROTOCOL_VERSION=1
250+
export WARP_CLIENT_VERSION="v0.2026.04.29.08.57.preview_01"
251+
252+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Read","session_id":"sess-456","cwd":"/Users/alice/my-project"}')
253+
assert_json_field "v is 1" "$PAYLOAD" ".v" "1"
254+
assert_json_field "agent is claude" "$PAYLOAD" ".agent" "claude"
255+
assert_json_field "event is tool_complete" "$PAYLOAD" ".event" "tool_complete"
256+
assert_json_field "session_id extracted" "$PAYLOAD" ".session_id" "sess-456"
257+
assert_json_field "cwd extracted" "$PAYLOAD" ".cwd" "/Users/alice/my-project"
258+
assert_json_field "project is basename of cwd" "$PAYLOAD" ".project" "my-project"
259+
assert_json_field "tool_name extracted" "$PAYLOAD" ".tool_name" "Read"
260+
261+
echo ""
262+
echo "--- Trailing slash in cwd ---"
263+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Read","session_id":"s1","cwd":"/Users/alice/project/"}')
264+
assert_json_field "trailing slash stripped for project" "$PAYLOAD" ".project" "project"
265+
266+
echo ""
267+
echo "--- Missing fields produce empty strings ---"
268+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Bash"}')
269+
assert_json_field "missing session_id is empty" "$PAYLOAD" ".session_id" ""
270+
assert_json_field "missing cwd is empty" "$PAYLOAD" ".cwd" ""
271+
assert_json_field "missing cwd gives empty project" "$PAYLOAD" ".project" ""
272+
assert_json_field "tool_name still works" "$PAYLOAD" ".tool_name" "Bash"
273+
274+
echo ""
275+
echo "--- Protocol version negotiation (inline) ---"
276+
export WARP_CLI_AGENT_PROTOCOL_VERSION=99
277+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Edit","session_id":"s1","cwd":"/tmp"}')
278+
assert_json_field "protocol capped to 1 when warp declares 99" "$PAYLOAD" ".v" "1"
279+
280+
export WARP_CLI_AGENT_PROTOCOL_VERSION=1
281+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Edit","session_id":"s1","cwd":"/tmp"}')
282+
assert_json_field "protocol is 1 when warp declares 1" "$PAYLOAD" ".v" "1"
283+
284+
echo ""
285+
echo "--- Non-numeric protocol version falls back to 1 ---"
286+
export WARP_CLI_AGENT_PROTOCOL_VERSION="garbage"
287+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Edit","session_id":"s1","cwd":"/tmp"}')
288+
assert_json_field "non-numeric protocol falls back to 1" "$PAYLOAD" ".v" "1"
289+
290+
echo ""
291+
echo "--- Early exit without protocol version ---"
292+
unset WARP_CLI_AGENT_PROTOCOL_VERSION
293+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Read","session_id":"s1","cwd":"/tmp"}')
294+
assert_eq "no output when WARP_CLI_AGENT_PROTOCOL_VERSION unset" "" "$PAYLOAD"
295+
296+
echo ""
297+
echo "--- Early exit for broken Warp version ---"
298+
export WARP_CLI_AGENT_PROTOCOL_VERSION=1
299+
export WARP_CLIENT_VERSION="v0.2026.03.25.08.24.stable_05"
300+
PAYLOAD=$(run_hook_capture "on-post-tool-use.sh" '{"tool_name":"Read","session_id":"s1","cwd":"/tmp"}')
301+
assert_eq "no output for broken stable version" "" "$PAYLOAD"
302+
303+
# Clean up
304+
unset WARP_CLI_AGENT_PROTOCOL_VERSION
305+
unset WARP_CLIENT_VERSION
306+
226307
# --- Summary ---
227308

228309
echo ""

0 commit comments

Comments
 (0)