agent-relay-plugin 0.4.32 → 0.4.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/hooks/approval-gate.sh +4 -0
- package/hooks/poll-inbox.sh +34 -5
- package/hooks/relay-monitor.sh +5 -0
- package/hooks/session-end.sh +4 -0
- package/hooks/set-status.sh +23 -0
- package/package.json +1 -1
package/hooks/approval-gate.sh
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
# Agent Relay plugin — approval gate for PreToolUse and PermissionDenied hooks.
|
|
3
3
|
# Enforces AGENT_RELAY_APPROVAL/profile approval policy: open (default), guarded, read-only.
|
|
4
4
|
|
|
5
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
6
|
+
exit 0
|
|
7
|
+
fi
|
|
8
|
+
|
|
5
9
|
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
6
10
|
source "${script_dir}/profile-lib.sh"
|
|
7
11
|
project=$(basename "${PWD:-unknown}")
|
package/hooks/poll-inbox.sh
CHANGED
|
@@ -3,6 +3,10 @@
|
|
|
3
3
|
# Each new message prints one stdout line (consumed by Monitor as a notification).
|
|
4
4
|
# Usage: poll-inbox.sh <relay-url> <agent-id> [interval-seconds]
|
|
5
5
|
|
|
6
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
7
|
+
exit 0
|
|
8
|
+
fi
|
|
9
|
+
|
|
6
10
|
RELAY_URL="$1"
|
|
7
11
|
AGENT_ID="$2"
|
|
8
12
|
INTERVAL="${3:-10}"
|
|
@@ -21,6 +25,7 @@ fi
|
|
|
21
25
|
# PID file so session-start.sh can find and kill us on /clear or /compact.
|
|
22
26
|
pid_file="/tmp/agent-relay-poll-${AGENT_ID}.pid"
|
|
23
27
|
status_file="/tmp/agent-relay-status-${AGENT_ID}.state"
|
|
28
|
+
delivered_file="/tmp/agent-relay-delivered-${AGENT_ID}.queue"
|
|
24
29
|
project=$(basename "${PWD:-unknown}")
|
|
25
30
|
if [ -n "$CLAUDE_RIG_NAME" ]; then rig="$CLAUDE_RIG_NAME"
|
|
26
31
|
elif [ -n "$CLAUDE_CONFIG_DIR" ]; then rig=$(basename "$CLAUDE_CONFIG_DIR")
|
|
@@ -48,6 +53,27 @@ current_status() {
|
|
|
48
53
|
esac
|
|
49
54
|
}
|
|
50
55
|
|
|
56
|
+
deliver_message() {
|
|
57
|
+
local line="$1"
|
|
58
|
+
if [ "${AGENT_RELAY_CLAUDE_DELIVERY:-monitor}" = "tmux" ] && [ -n "${AGENT_RELAY_CLAUDE_TMUX_SESSION:-}" ] && command -v tmux >/dev/null 2>&1; then
|
|
59
|
+
if tmux set-buffer "$line" 2>/dev/null &&
|
|
60
|
+
tmux paste-buffer -t "$AGENT_RELAY_CLAUDE_TMUX_SESSION" 2>/dev/null &&
|
|
61
|
+
tmux send-keys -t "$AGENT_RELAY_CLAUDE_TMUX_SESSION" C-m 2>/dev/null; then
|
|
62
|
+
return 0
|
|
63
|
+
fi
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
printf '%s\n' "$line"
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
mark_read_or_queue() {
|
|
70
|
+
local mid="$1"
|
|
71
|
+
curl -s -X PATCH "${RELAY_URL}/api/messages/${mid}" "${auth_header_args[@]}" \
|
|
72
|
+
-H 'Content-Type: application/json' \
|
|
73
|
+
-d "{\"readBy\":\"${AGENT_ID}\"}" > /dev/null 2>&1 ||
|
|
74
|
+
printf '%s\n' "$mid" >> "$delivered_file"
|
|
75
|
+
}
|
|
76
|
+
|
|
51
77
|
re_register() {
|
|
52
78
|
local machine rig project reg_code
|
|
53
79
|
machine=$(hostname)
|
|
@@ -88,6 +114,11 @@ marked_ready=false
|
|
|
88
114
|
# Save parent PID (Claude Code wrapper) — if it dies, we're orphaned.
|
|
89
115
|
_parent_pid="$PPID"
|
|
90
116
|
while true; do
|
|
117
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
118
|
+
set_status "offline"
|
|
119
|
+
exit 0
|
|
120
|
+
fi
|
|
121
|
+
|
|
91
122
|
# Exit if parent process is gone — prevents orphaned monitors from heartbeating forever.
|
|
92
123
|
if ! kill -0 "$_parent_pid" 2>/dev/null; then
|
|
93
124
|
set_status "offline"
|
|
@@ -161,11 +192,9 @@ while true; do
|
|
|
161
192
|
fi
|
|
162
193
|
fi
|
|
163
194
|
|
|
164
|
-
printf '%s' "$msg" | jq -r '(.meta.pairId // empty) as $pair | (if $pair != "" then " [pair:\($pair)]" else "" end) as $pairText | if .type == "system" then "⚠ SYSTEM [msg:\(.id)]\($pairText): \(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
-H 'Content-Type: application/json' \
|
|
168
|
-
-d "{\"readBy\":\"${AGENT_ID}\"}" > /dev/null 2>&1 || true
|
|
195
|
+
line=$(printf '%s' "$msg" | jq -r '(.meta.pairId // empty) as $pair | (if $pair != "" then " [pair:\($pair)]" else "" end) as $pairText | (.body | gsub("\r"; "\\r") | gsub("\n"; "\\n")) as $body | if .type == "system" then "⚠ SYSTEM [msg:\(.id)]\($pairText): \($body)" else "[msg:\(.id)]\($pairText) \(.from) → \(.to) | \(.subject // "(no subject)"): \($body)" end')
|
|
196
|
+
deliver_message "$line"
|
|
197
|
+
mark_read_or_queue "$mid"
|
|
169
198
|
done
|
|
170
199
|
since_id=$(echo "$msgs" | jq '[.[].id] | max')
|
|
171
200
|
fi
|
package/hooks/relay-monitor.sh
CHANGED
|
@@ -4,6 +4,10 @@
|
|
|
4
4
|
# Runs automatically via monitors.json — no user interaction required.
|
|
5
5
|
# CLAUDE_CODE_SESSION_ID = stable session key for state file coordination between monitor and hooks.
|
|
6
6
|
|
|
7
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
8
|
+
exit 0
|
|
9
|
+
fi
|
|
10
|
+
|
|
7
11
|
RELAY_URL="${AGENT_RELAY_URL:-http://localhost:4850}"
|
|
8
12
|
script_dir=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
9
13
|
source "${script_dir}/profile-lib.sh"
|
|
@@ -136,6 +140,7 @@ To check messages:
|
|
|
136
140
|
|
|
137
141
|
To mark read:
|
|
138
142
|
curl -s -X PATCH ${RELAY_URL}/api/messages/ID${auth_header_example} -H 'Content-Type: application/json' -d '{"readBy":"${agent_id}"}'
|
|
143
|
+
The inbox monitor marks read after it successfully delivers a message to Claude. The Stop hook retries any failed read acknowledgements.
|
|
139
144
|
|
|
140
145
|
To find agents by capability:
|
|
141
146
|
curl -s${auth_header_example} '${RELAY_URL}/api/agents/find?capability=review'
|
package/hooks/session-end.sh
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
# Agent Relay plugin — SessionEnd hook
|
|
3
3
|
# Marks this session's agent as offline using state file written by relay-monitor.
|
|
4
4
|
|
|
5
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
6
|
+
exit 0
|
|
7
|
+
fi
|
|
8
|
+
|
|
5
9
|
RELAY_URL="${AGENT_RELAY_URL:-http://localhost:4850}"
|
|
6
10
|
auth_header_args=()
|
|
7
11
|
if [ -n "${AGENT_RELAY_TOKEN:-}" ]; then
|
package/hooks/set-status.sh
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
# Agent Relay plugin — status update helper for Claude turn hooks.
|
|
3
3
|
# Usage: set-status.sh <online|idle|busy|offline>
|
|
4
4
|
|
|
5
|
+
if [ "${AGENT_RELAY_DISABLED:-}" = "1" ]; then
|
|
6
|
+
exit 0
|
|
7
|
+
fi
|
|
8
|
+
|
|
5
9
|
status="${1:-}"
|
|
6
10
|
case "$status" in
|
|
7
11
|
online|idle|busy|offline) ;;
|
|
@@ -32,4 +36,23 @@ curl -s -o /dev/null -X PATCH "${RELAY_URL}/api/agents/${agent_id}/status" "${au
|
|
|
32
36
|
-d "{\"status\":\"${status}\"}" \
|
|
33
37
|
2>/dev/null || true
|
|
34
38
|
|
|
39
|
+
if [ "$status" = "idle" ]; then
|
|
40
|
+
delivered_file="/tmp/agent-relay-delivered-${agent_id}.queue"
|
|
41
|
+
if [ -s "$delivered_file" ]; then
|
|
42
|
+
processing_file="${delivered_file}.$$"
|
|
43
|
+
if mv "$delivered_file" "$processing_file" 2>/dev/null; then
|
|
44
|
+
sort -n -u "$processing_file" | while IFS= read -r mid; do
|
|
45
|
+
case "$mid" in
|
|
46
|
+
''|*[!0-9]*) continue ;;
|
|
47
|
+
esac
|
|
48
|
+
curl -s -o /dev/null -X PATCH "${RELAY_URL}/api/messages/${mid}" "${auth_header_args[@]}" \
|
|
49
|
+
-H 'Content-Type: application/json' \
|
|
50
|
+
-d "{\"readBy\":\"${agent_id}\"}" \
|
|
51
|
+
2>/dev/null || printf '%s\n' "$mid" >> "$delivered_file"
|
|
52
|
+
done
|
|
53
|
+
rm -f "$processing_file"
|
|
54
|
+
fi
|
|
55
|
+
fi
|
|
56
|
+
fi
|
|
57
|
+
|
|
35
58
|
exit 0
|
package/package.json
CHANGED