Community Skills (32): - jat: jat-start, jat-verify, jat-complete - pi-mono: codex-cli, codex-5.3-prompting, interactive-shell - picoclaw: github, weather, tmux, summarize, skill-creator - dyad: 18 skills (swarm-to-plan, multi-pr-review, fix-issue, lint, etc.) - dexter: dcf valuation skill Agents (23): - pi-mono subagents: scout, planner, reviewer, worker - toad: 19 agent configs (Claude, Codex, Gemini, Copilot, OpenCode, etc.) System Prompts (91): - Anthropic: 15 Claude prompts (opus-4.6, code, cowork, etc.) - OpenAI: 49 GPT prompts (gpt-5 series, o3, o4-mini, tools) - Google: 13 Gemini prompts (2.5-pro, 3-pro, workspace, cli) - xAI: 5 Grok prompts - Other: 9 misc prompts (Notion, Raycast, Warp, Kagi, etc.) Hooks (9): - JAT hooks for session management, signal tracking, activity logging Prompts (6): - pi-mono templates for PR review, issue analysis, changelog audit Sources analyzed: jat, ralph-desktop, toad, pi-mono, cmux, pi-interactive-shell, craft-agents-oss, dexter, picoclaw, dyad, system_prompts_leaks, Prometheus, zed, clawdbot, OS-Copilot, and more
86 lines
2.4 KiB
Bash
Executable File
86 lines
2.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# monitor-output.sh - Real-time output activity monitor
|
|
#
|
|
# Monitors tmux pane output to detect when agent is actively generating text.
|
|
# Writes ephemeral state to /tmp/jat-activity-{session}.json for IDE polling.
|
|
#
|
|
# Usage: monitor-output.sh <tmux-session-name>
|
|
# Started by: user-prompt-signal.sh (on user message)
|
|
# Terminates: After 30 seconds of no output change
|
|
#
|
|
# States:
|
|
# generating - Output is growing (agent writing text)
|
|
# thinking - Output stable for 2+ seconds (agent processing)
|
|
# idle - Output stable for 30+ seconds (agent waiting)
|
|
|
|
set -euo pipefail
|
|
|
|
TMUX_SESSION="${1:-}"
|
|
if [[ -z "$TMUX_SESSION" ]]; then
|
|
exit 1
|
|
fi
|
|
|
|
ACTIVITY_FILE="/tmp/jat-activity-${TMUX_SESSION}.json"
|
|
PID_FILE="/tmp/jat-monitor-${TMUX_SESSION}.pid"
|
|
|
|
# Write our PID so we can be killed by other hooks
|
|
echo $$ > "$PID_FILE"
|
|
|
|
# Cleanup on exit
|
|
trap "rm -f '$PID_FILE'" EXIT
|
|
|
|
prev_len=0
|
|
idle_count=0
|
|
last_state=""
|
|
touch_count=0
|
|
|
|
write_state() {
|
|
local state="$1"
|
|
local force="${2:-false}"
|
|
# Write if state changed OR if force=true (to update mtime for freshness check)
|
|
if [[ "$state" != "$last_state" ]] || [[ "$force" == "true" ]]; then
|
|
echo "{\"state\":\"${state}\",\"since\":\"$(date -Iseconds)\",\"tmux_session\":\"${TMUX_SESSION}\"}" > "$ACTIVITY_FILE"
|
|
last_state="$state"
|
|
touch_count=0
|
|
fi
|
|
}
|
|
|
|
# Initial state
|
|
write_state "generating"
|
|
|
|
while true; do
|
|
# Capture current pane content length
|
|
curr_len=$(tmux capture-pane -t "$TMUX_SESSION" -p 2>/dev/null | wc -c || echo "0")
|
|
|
|
if [[ "$curr_len" -gt "$prev_len" ]]; then
|
|
# Output is growing = agent generating text
|
|
write_state "generating"
|
|
idle_count=0
|
|
else
|
|
# Output stable
|
|
((idle_count++)) || true
|
|
|
|
if [[ $idle_count -gt 20 ]]; then
|
|
# 2+ seconds of no change = thinking/processing
|
|
write_state "thinking"
|
|
fi
|
|
|
|
if [[ $idle_count -gt 300 ]]; then
|
|
# 30+ seconds of no change = idle, self-terminate
|
|
write_state "idle"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Keep file timestamp fresh for IDE staleness check (every ~2 seconds)
|
|
# IDE considers activity older than 30s as stale, so we update at least every 20 iterations
|
|
((touch_count++)) || true
|
|
if [[ $touch_count -gt 20 ]]; then
|
|
write_state "$last_state" true
|
|
fi
|
|
|
|
prev_len="$curr_len"
|
|
sleep 0.1
|
|
done
|