diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index c898bff..ab081b9 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -10,7 +10,7 @@ "name": "warp", "description": "Native Warp notifications when Claude completes tasks or needs input", "source": "./plugins/warp", - "version": "2.1.0", + "version": "2.2.0", "category": "productivity", "tags": ["notifications", "terminal", "warp"] }, diff --git a/plugins/warp/.claude-plugin/plugin.json b/plugins/warp/.claude-plugin/plugin.json index 8dd9247..1e29217 100644 --- a/plugins/warp/.claude-plugin/plugin.json +++ b/plugins/warp/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "warp", "description": "Warp terminal integration for Claude Code - native notifications, and more to come", - "version": "2.1.0", + "version": "2.2.0", "author": { "name": "Warp", "url": "https://warp.dev" diff --git a/plugins/warp/hooks/hooks.json b/plugins/warp/hooks/hooks.json index b2273b4..ba32f28 100644 --- a/plugins/warp/hooks/hooks.json +++ b/plugins/warp/hooks/hooks.json @@ -62,6 +62,16 @@ } ] } + ], + "StopFailure": [ + { + "hooks": [ + { + "type": "command", + "command": "${CLAUDE_PLUGIN_ROOT}/scripts/on-stop-failure.sh" + } + ] + } ] } } diff --git a/plugins/warp/scripts/on-stop-failure.sh b/plugins/warp/scripts/on-stop-failure.sh new file mode 100755 index 0000000..b170326 --- /dev/null +++ b/plugins/warp/scripts/on-stop-failure.sh @@ -0,0 +1,53 @@ +#!/bin/bash +# Hook script for Claude Code StopFailure event +# Sends a structured Warp notification when Claude's turn ends due to an API error + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/should-use-structured.sh" + +# Legacy Warp clients that don't support structured events don't get a +# stop_failure notification — they have no UI to act on it. +if ! should_use_structured; then + exit 0 +fi + +source "$SCRIPT_DIR/build-payload.sh" + +# Read hook input from stdin +INPUT=$(cat) + +# Extract the error type (e.g. "rate_limit") and human-readable message. +ERROR_TYPE=$(echo "$INPUT" | jq -r '.error // empty' 2>/dev/null) +ERROR_MESSAGE=$(echo "$INPUT" | jq -r '.last_assistant_message // empty' 2>/dev/null) + +# Also try to extract the last user query from the transcript so Warp can +# show it as the notification title, matching the Stop hook behaviour. +TRANSCRIPT_PATH=$(echo "$INPUT" | jq -r '.transcript_path // empty' 2>/dev/null) +QUERY="" +if [ -n "$TRANSCRIPT_PATH" ] && [ -f "$TRANSCRIPT_PATH" ]; then + QUERY=$(jq -rs ' + [ + .[] | select(.type == "user") | + if .message.content | type == "string" then . + elif [.message.content[] | select(.type == "text")] | length > 0 then . + else empty + end + ] | last | + if .message.content | type == "array" + then [.message.content[] | select(.type == "text") | .text] | join(" ") + else .message.content // empty + end + ' "$TRANSCRIPT_PATH" 2>/dev/null) + + if [ -n "$QUERY" ] && [ ${#QUERY} -gt 200 ]; then + QUERY="${QUERY:0:197}..." + fi +fi + +BODY=$(build_payload "$INPUT" "stop_failure" \ + --arg query "$QUERY" \ + --arg response "$ERROR_MESSAGE" \ + --arg error_type "$ERROR_TYPE" \ + --arg transcript_path "$TRANSCRIPT_PATH") + +"$SCRIPT_DIR/warp-notify.sh" "warp://cli-agent" "$BODY"