ScuttleBot

scuttlebot / skills / openai-relay / hooks / scuttlebot-post.sh
Source Blame History 123 lines
50baf1a… lmata 1 #!/bin/bash
50baf1a… lmata 2 # PostToolUse hook for OpenAI agents (Codex-style). Posts activity to scuttlebot IRC.
50baf1a… lmata 3
50baf1a… lmata 4 SCUTTLEBOT_CONFIG_FILE="${SCUTTLEBOT_CONFIG_FILE:-$HOME/.config/scuttlebot-relay.env}"
50baf1a… lmata 5 if [ -f "$SCUTTLEBOT_CONFIG_FILE" ]; then
50baf1a… lmata 6 set -a
50baf1a… lmata 7 . "$SCUTTLEBOT_CONFIG_FILE"
50baf1a… lmata 8 set +a
50baf1a… lmata 9 fi
1d3caa2… lmata 10 if [ -n "${SCUTTLEBOT_CHANNEL_STATE_FILE:-}" ] && [ -f "$SCUTTLEBOT_CHANNEL_STATE_FILE" ]; then
1d3caa2… lmata 11 set -a
1d3caa2… lmata 12 . "$SCUTTLEBOT_CHANNEL_STATE_FILE"
1d3caa2… lmata 13 set +a
1d3caa2… lmata 14 fi
50baf1a… lmata 15
50baf1a… lmata 16 SCUTTLEBOT_URL="${SCUTTLEBOT_URL:-http://localhost:8080}"
50baf1a… lmata 17 SCUTTLEBOT_TOKEN="${SCUTTLEBOT_TOKEN}"
50baf1a… lmata 18 SCUTTLEBOT_CHANNEL="${SCUTTLEBOT_CHANNEL:-general}"
50baf1a… lmata 19 SCUTTLEBOT_HOOKS_ENABLED="${SCUTTLEBOT_HOOKS_ENABLED:-1}"
50baf1a… lmata 20 SCUTTLEBOT_ACTIVITY_VIA_BROKER="${SCUTTLEBOT_ACTIVITY_VIA_BROKER:-0}"
1d3caa2… lmata 21
1d3caa2… lmata 22 normalize_channel() {
1d3caa2… lmata 23 local channel="$1"
1d3caa2… lmata 24 channel="${channel//[$' \t\r\n']/}"
1d3caa2… lmata 25 channel="${channel#\#}"
1d3caa2… lmata 26 printf '%s' "$channel"
1d3caa2… lmata 27 }
1d3caa2… lmata 28
1d3caa2… lmata 29 relay_channels() {
1d3caa2… lmata 30 local raw="${SCUTTLEBOT_CHANNELS:-$SCUTTLEBOT_CHANNEL}"
1d3caa2… lmata 31 local IFS=','
1d3caa2… lmata 32 local item channel seen=""
1d3caa2… lmata 33 read -r -a items <<< "$raw"
1d3caa2… lmata 34 for item in "${items[@]}"; do
1d3caa2… lmata 35 channel=$(normalize_channel "$item")
1d3caa2… lmata 36 [ -n "$channel" ] || continue
1d3caa2… lmata 37 case ",$seen," in
1d3caa2… lmata 38 *,"$channel",*) ;;
1d3caa2… lmata 39 *)
1d3caa2… lmata 40 seen="${seen:+$seen,}$channel"
1d3caa2… lmata 41 printf '%s\n' "$channel"
1d3caa2… lmata 42 ;;
1d3caa2… lmata 43 esac
1d3caa2… lmata 44 done
1d3caa2… lmata 45 }
1d3caa2… lmata 46
1d3caa2… lmata 47 post_message() {
1d3caa2… lmata 48 local text="$1"
1d3caa2… lmata 49 local payload
1d3caa2… lmata 50 payload="{\"text\": $(printf '%s' "$text" | jq -Rs .), \"nick\": \"$SCUTTLEBOT_NICK\"}"
1d3caa2… lmata 51 for channel in $(relay_channels); do
1d3caa2… lmata 52 curl -sf -X POST "$SCUTTLEBOT_URL/v1/channels/$channel/messages" \
1d3caa2… lmata 53 --connect-timeout 1 \
1d3caa2… lmata 54 --max-time 2 \
1d3caa2… lmata 55 -H "Authorization: Bearer $SCUTTLEBOT_TOKEN" \
1d3caa2… lmata 56 -H "Content-Type: application/json" \
1d3caa2… lmata 57 -d "$payload" \
1d3caa2… lmata 58 > /dev/null || true
1d3caa2… lmata 59 done
1d3caa2… lmata 60 }
50baf1a… lmata 61
50baf1a… lmata 62 input=$(cat)
50baf1a… lmata 63
50baf1a… lmata 64 tool=$(echo "$input" | jq -r '.tool_name // empty')
50baf1a… lmata 65 cwd=$(echo "$input" | jq -r '.cwd // empty')
50baf1a… lmata 66
50baf1a… lmata 67 sanitize() {
50baf1a… lmata 68 printf '%s' "$1" | tr -cs '[:alnum:]_-' '-'
50baf1a… lmata 69 }
50baf1a… lmata 70
50baf1a… lmata 71 if [ -z "$cwd" ]; then
50baf1a… lmata 72 cwd=$(pwd)
50baf1a… lmata 73 fi
50baf1a… lmata 74 base_name=$(sanitize "$(basename "$cwd")")
50baf1a… lmata 75 session_suffix="${SCUTTLEBOT_SESSION_ID:-${CODEX_SESSION_ID:-$PPID}}"
50baf1a… lmata 76 session_suffix=$(sanitize "$session_suffix")
50baf1a… lmata 77 default_nick="codex-${base_name}-${session_suffix}"
50baf1a… lmata 78 SCUTTLEBOT_NICK="${SCUTTLEBOT_NICK:-$default_nick}"
50baf1a… lmata 79
50baf1a… lmata 80 [ "$SCUTTLEBOT_HOOKS_ENABLED" = "0" ] && exit 0
50baf1a… lmata 81 [ "$SCUTTLEBOT_HOOKS_ENABLED" = "false" ] && exit 0
50baf1a… lmata 82 [ "$SCUTTLEBOT_ACTIVITY_VIA_BROKER" = "1" ] && exit 0
50baf1a… lmata 83 [ "$SCUTTLEBOT_ACTIVITY_VIA_BROKER" = "true" ] && exit 0
50baf1a… lmata 84 [ -z "$SCUTTLEBOT_TOKEN" ] && exit 0
50baf1a… lmata 85
50baf1a… lmata 86 case "$tool" in
50baf1a… lmata 87 Bash)
50baf1a… lmata 88 cmd=$(echo "$input" | jq -r '.tool_input.command // empty' | head -c 120)
50baf1a… lmata 89 msg="› $cmd"
50baf1a… lmata 90 ;;
50baf1a… lmata 91 Read)
50baf1a… lmata 92 file=$(echo "$input" | jq -r '.tool_input.file_path // empty' | sed "s|$cwd/||")
50baf1a… lmata 93 msg="read $file"
50baf1a… lmata 94 ;;
50baf1a… lmata 95 Edit)
50baf1a… lmata 96 file=$(echo "$input" | jq -r '.tool_input.file_path // empty' | sed "s|$cwd/||")
50baf1a… lmata 97 msg="edit $file"
50baf1a… lmata 98 ;;
50baf1a… lmata 99 Write)
50baf1a… lmata 100 file=$(echo "$input" | jq -r '.tool_input.file_path // empty' | sed "s|$cwd/||")
50baf1a… lmata 101 msg="write $file"
50baf1a… lmata 102 ;;
50baf1a… lmata 103 Glob)
50baf1a… lmata 104 pattern=$(echo "$input" | jq -r '.tool_input.pattern // empty')
50baf1a… lmata 105 msg="glob $pattern"
50baf1a… lmata 106 ;;
50baf1a… lmata 107 Grep)
50baf1a… lmata 108 pattern=$(echo "$input" | jq -r '.tool_input.pattern // empty')
50baf1a… lmata 109 msg="grep \"$pattern\""
50baf1a… lmata 110 ;;
50baf1a… lmata 111 Agent)
50baf1a… lmata 112 desc=$(echo "$input" | jq -r '.tool_input.description // empty' | head -c 80)
50baf1a… lmata 113 msg="spawn agent: $desc"
50baf1a… lmata 114 ;;
50baf1a… lmata 115 *)
50baf1a… lmata 116 msg="$tool"
50baf1a… lmata 117 ;;
50baf1a… lmata 118 esac
50baf1a… lmata 119
50baf1a… lmata 120 [ -z "$msg" ] && exit 0
50baf1a… lmata 121
1d3caa2… lmata 122 post_message "$msg"
50baf1a… lmata 123 exit 0

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button