-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcodex-status-monitor.sh
More file actions
executable file
·91 lines (83 loc) · 3.4 KB
/
codex-status-monitor.sh
File metadata and controls
executable file
·91 lines (83 loc) · 3.4 KB
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
90
91
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=shared/hooks/wavemill-hook-protocol.sh
source "$SCRIPT_DIR/wavemill-hook-protocol.sh"
# Outside a wavemill-launched environment, act as a sink instead of exiting
# immediately. Exiting here would close the downstream side of the Codex JSON
# pipeline and can cause Codex to abort with a broken pipe.
if [[ -z "${WAVEMILL_SESSION:-}" ]] || [[ -z "${WAVEMILL_ISSUE:-}" ]] || ! command -v jq >/dev/null 2>&1; then
cat >/dev/null || true
exit 0
fi
# Read Codex JSONL events from stdin and map them onto the shared wavemill
# status protocol. Unknown events are ignored; end-of-stream marks the
# session as idle so crashed or exited agents do not remain "working" forever.
last_state=""
completed=false
while IFS= read -r line; do
[[ -n "$line" ]] || continue
# Extract event type and detail from JSONL
event=$(printf '%s\n' "$line" | jq -r '.type // empty' 2>/dev/null || true)
[[ -n "$event" ]] || continue
detail=""
case "$event" in
response_item)
payload_type=$(printf '%s\n' "$line" | jq -r '.payload.type // empty' 2>/dev/null || true)
case "$payload_type" in
function_call)
detail=$(printf '%s\n' "$line" | jq -r '.payload.function.name // empty' 2>/dev/null || true)
wavemill_hook_write "working" "$event" "$detail" "codex"
last_state="working"
;;
function_call_output|tool_result)
wavemill_hook_write "working" "$event" "$payload_type" "codex"
last_state="working"
;;
esac
;;
exec_command|tool_use|function_call|agent_message)
wavemill_hook_write "working" "$event" "" "codex"
last_state="working"
;;
notification)
detail=$(printf '%s\n' "$line" | jq -r '.message // .text // empty' 2>/dev/null || true)
wavemill_hook_write "waiting" "$event" "$detail" "codex"
last_state="waiting"
;;
error|agent_error|execution_error|api_error)
detail=$(printf '%s\n' "$line" | jq -r '.error.message // .message // .error // .text // empty' 2>/dev/null || true)
if [[ -z "$detail" ]]; then
detail=$(printf '%s\n' "$line" | jq -r '.error_type // .type // empty' 2>/dev/null || true)
fi
if [[ -z "$detail" ]]; then
detail=$(printf '%s\n' "$line" | jq -r '.error // empty' 2>/dev/null | head -c 200 || true)
fi
wavemill_hook_write "error" "$event" "$detail" "codex"
last_state="error"
;;
task_complete|agent_turn_complete|response.completed|response_complete)
wavemill_hook_write "idle" "$event" "" "codex"
last_state="idle"
completed=true
;;
esac
done
stderr_snippet=""
if [[ -n "${CODEX_STDERR_LOG:-}" ]] && [[ -s "$CODEX_STDERR_LOG" ]]; then
stderr_snippet="$(head -c 200 "$CODEX_STDERR_LOG" 2>/dev/null | tr '\n' ' ' | tr '\r' ' ' || true)"
fi
# Stream ended. Preserve explicit errors, mark successful completions as idle,
# and treat unexpected EOF as an error so the dashboard does not show a dead
# agent as still running or cleanly exited.
if [[ "$last_state" != "error" ]]; then
if [[ "$completed" == "true" ]]; then
wavemill_hook_write "idle" "stream_end" "" "codex"
else
detail="unexpected termination"
if [[ -n "$stderr_snippet" ]]; then
detail="${detail}: ${stderr_snippet}"
fi
wavemill_hook_write "error" "unexpected_eof" "$detail" "codex"
fi
fi