File size: 3,341 Bytes
df112f9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/bin/sh
# Observation-only hook for native CLI "this dialog is actually open" events.
# It never approves, rejects or otherwise participates in the decision.

[ -n "$AM_ID" ] || exit 0
case "$AM_ID" in *[!a-zA-Z0-9_-]*) exit 0 ;; esac
[ -n "$AM_RUN_ID" ] || exit 0
case "$AM_RUN_ID" in *[!a-zA-Z0-9_-]*) exit 0 ;; esac
case "$AM_PANE_PID" in '' | *[!0-9]*) exit 0 ;; esac
command -v jq >/dev/null 2>&1 || exit 0

payload=$(mktemp "${TMPDIR:-/tmp}/am-input-hook.XXXXXX") || exit 0
trap 'rm -f "$payload"' EXIT HUP INT TERM
cat > "$payload" || exit 0

kind=
source=
clear=
case "$AM_CLI" in
  claude)
    # A global Claude config is inherited by nested Claude processes. Its
    # official entrypoint/pid fields let us keep only this pane's root CLI.
    [ "$CLAUDE_CODE_ENTRYPOINT" = "cli" ] || exit 0
    case "$CLAUDE_PID" in '' | *[!0-9]*) exit 0 ;; esac
    if [ "$CLAUDE_PID" != "$AM_PANE_PID" ]; then
      stat=$(cat "/proc/$CLAUDE_PID/stat" 2>/dev/null) || exit 0
      rest=${stat##*) }
      rest=${rest#* }
      [ "${rest%% *}" = "$AM_PANE_PID" ] || exit 0
    fi
    case "$(jq -r '.hook_event_name // empty' "$payload")" in
      Notification)
        case "$(jq -r '.notification_type // empty' "$payload")" in
          permission_prompt) kind=permission ;;
          elicitation_dialog | elicitation_url_dialog | agent_needs_input) kind=question ;;
          agent_completed) clear=1 ;;
          *) exit 0 ;;
        esac
        ;;
      PostToolBatch | Stop | SessionEnd | ElicitationResult | UserPromptSubmit) clear=1 ;;
      *) exit 0 ;;
    esac
    source=claude-notification
    ;;
  gemini)
    # Gemini spawns `bash -c` for command hooks. Bash normally execs this
    # single-command script, but allowing that one runner process keeps the
    # attribution correct if it forks instead. A Gemini started by an agent
    # tool still has its own CLI and tool shell between here and the pane root.
    stat=$(cat "/proc/$$/stat" 2>/dev/null) || exit 0
    rest=${stat##*) }
    rest=${rest#* }
    parent=${rest%% *}
    if [ "$parent" != "$AM_PANE_PID" ]; then
      stat=$(cat "/proc/$parent/stat" 2>/dev/null) || exit 0
      rest=${stat##*) }
      rest=${rest#* }
      [ "${rest%% *}" = "$AM_PANE_PID" ] || exit 0
    fi
    case "$(jq -r '.hook_event_name // empty' "$payload")" in
      Notification)
        [ "$(jq -r '.notification_type // empty' "$payload")" = "ToolPermission" ] || exit 0
        if [ "$(jq -r '.details.type // empty' "$payload")" = "ask_user" ]; then kind=question; else kind=permission; fi
        ;;
      AfterAgent | SessionEnd) clear=1 ;;
      *) exit 0 ;;
    esac
    source=gemini-notification
    ;;
  *) exit 0 ;;
esac

d=${AM_INPUT_REQUIRED_DIR:-/tmp/am-input-required}
mkdir -p "$d" 2>/dev/null || exit 0
if [ -n "$clear" ]; then
  file="$d/$AM_ID.json"
  [ "$(jq -r '.runId // empty' "$file" 2>/dev/null)" = "$AM_RUN_ID" ] || exit 0
  [ "$(jq -r '.cli // empty' "$file" 2>/dev/null)" = "$AM_CLI" ] || exit 0
  rm -f "$file"
  exit 0
fi
at=$(( $(date +%s) * 1000 ))
tmp="$d/$AM_ID.json.$$.tmp"
jq -n --arg amId "$AM_ID" --arg runId "$AM_RUN_ID" --arg cli "$AM_CLI" \
  --arg kind "$kind" --arg source "$source" --argjson at "$at" \
  '{amId:$amId,runId:$runId,cli:$cli,kind:$kind,source:$source,at:$at}' > "$tmp" 2>/dev/null \
  && mv -f "$tmp" "$d/$AM_ID.json"
exit 0