script: reinforced auto-agent scripts
CI / status-check (push) Blocked by required conditions
CI / benchmark-publish (push) Waiting to run
CI / push-validation (push) Successful in 40s
CI / helm (push) Successful in 53s
CI / build (push) Successful in 1m7s
CI / quality (push) Successful in 1m31s
CI / lint (push) Successful in 1m37s
CI / typecheck (push) Successful in 1m39s
CI / security (push) Successful in 1m46s
CI / integration_tests (push) Successful in 4m40s
CI / e2e_tests (push) Successful in 5m10s
CI / unit_tests (push) Successful in 7m10s
CI / docker (push) Waiting to run
CI / coverage (push) Has started running
CI / status-check (push) Blocked by required conditions
CI / benchmark-publish (push) Waiting to run
CI / push-validation (push) Successful in 40s
CI / helm (push) Successful in 53s
CI / build (push) Successful in 1m7s
CI / quality (push) Successful in 1m31s
CI / lint (push) Successful in 1m37s
CI / typecheck (push) Successful in 1m39s
CI / security (push) Successful in 1m46s
CI / integration_tests (push) Successful in 4m40s
CI / e2e_tests (push) Successful in 5m10s
CI / unit_tests (push) Successful in 7m10s
CI / docker (push) Waiting to run
CI / coverage (push) Has started running
This commit is contained in:
Executable → Regular
+110
-15
@@ -19,6 +19,7 @@ BASE="http://${HOST}:${PORT}"
|
||||
AGENT="auto-agents"
|
||||
PROMPT="Complete the current project's milestones up to and including v3.7.0 to a production ready state"
|
||||
HEALTH_TIMEOUT=60 # seconds to wait for the server to become healthy
|
||||
MAX_IDLE_PER_MINUTE=10
|
||||
|
||||
# ── Internal state ────────────────────────────────────────────────────────
|
||||
SERVER_PID=""
|
||||
@@ -27,6 +28,8 @@ SESSION_ID=""
|
||||
STOP_LOOP=false
|
||||
LAST_SIGINT=0
|
||||
OWN_SERVER=false
|
||||
N=0
|
||||
IDLE_EVENTS_FILE=""
|
||||
|
||||
# ── Helpers ───────────────────────────────────────────────────────────────
|
||||
die() { printf "ERROR: %s\n" "$*" >&2; exit 1; }
|
||||
@@ -42,6 +45,9 @@ check_opencode_running() {
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
if [[ -n "$IDLE_EVENTS_FILE" ]]; then
|
||||
rm -f "$IDLE_EVENTS_FILE" 2>/dev/null || true
|
||||
fi
|
||||
if $OWN_SERVER && [[ -n "$SERVER_PID" ]] && kill -0 "$SERVER_PID" 2>/dev/null; then
|
||||
log "Stopping opencode server (PID $SERVER_PID)..."
|
||||
kill "$SERVER_PID" 2>/dev/null
|
||||
@@ -72,6 +78,83 @@ handle_sigint() {
|
||||
trap handle_sigint INT
|
||||
trap cleanup EXIT
|
||||
|
||||
# ── Idle-event tracking ───────────────────────────────────────────────────
|
||||
init_idle_tracking() {
|
||||
IDLE_EVENTS_FILE="/tmp/opencode-builder-idle-events-${SESSION_ID}.txt"
|
||||
: > "$IDLE_EVENTS_FILE" 2>/dev/null || true
|
||||
}
|
||||
|
||||
record_idle_event() {
|
||||
local now
|
||||
now=$(date +%s)
|
||||
echo "$now" >> "$IDLE_EVENTS_FILE"
|
||||
}
|
||||
|
||||
count_idle_events_last_minute() {
|
||||
local now cutoff
|
||||
now=$(date +%s)
|
||||
cutoff=$((now - 60))
|
||||
if [[ -f "$IDLE_EVENTS_FILE" ]]; then
|
||||
awk -v c="$cutoff" '$1 > c {count++} END {print count+0}' "$IDLE_EVENTS_FILE" 2>/dev/null
|
||||
else
|
||||
echo 0
|
||||
fi
|
||||
}
|
||||
|
||||
# ── Session lifecycle ─────────────────────────────────────────────────────
|
||||
create_session() {
|
||||
log "Creating session..."
|
||||
SESSION_ID=$(
|
||||
curl -sf -X POST "${BASE}/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title":"auto-agents"}' \
|
||||
| jq -r '.id'
|
||||
) || die "Failed to create session"
|
||||
|
||||
[[ -n "$SESSION_ID" && "$SESSION_ID" != "null" ]] || die "Session ID is empty or null"
|
||||
log "Session ID: ${SESSION_ID}"
|
||||
init_idle_tracking
|
||||
}
|
||||
|
||||
delete_session() {
|
||||
local sid="$1"
|
||||
if [[ -n "$sid" ]]; then
|
||||
curl -sf -X DELETE "${BASE}/session/${sid}" >/dev/null 2>&1 || true
|
||||
fi
|
||||
}
|
||||
|
||||
restart_session() {
|
||||
log "Session appears broken (>${MAX_IDLE_PER_MINUTE} idle events/min). Restarting..."
|
||||
local old_sid="$SESSION_ID"
|
||||
SESSION_ID=""
|
||||
N=0
|
||||
delete_session "$old_sid"
|
||||
create_session
|
||||
send_message "$INIT_BODY"
|
||||
log "Initial prompt complete after restart."
|
||||
}
|
||||
|
||||
# ── Question handling ─────────────────────────────────────────────────────
|
||||
# Queries the OpenCode /question endpoint and rejects any pending questions
|
||||
# that belong to the supplied session. Returns the number of questions that
|
||||
# were successfully dismissed.
|
||||
dismiss_pending_questions() {
|
||||
local sid="$1"
|
||||
local questions_json dismissed qid
|
||||
|
||||
questions_json=$(curl -sf "${BASE}/question" 2>/dev/null) || return 1
|
||||
|
||||
dismissed=0
|
||||
for qid in $(echo "$questions_json" | jq -r --arg sid "$sid" '.[] | select(.sessionID == $sid) | .id'); do
|
||||
log "Dismissing question $qid"
|
||||
if curl -sf -X POST "${BASE}/question/${qid}/reject" >/dev/null 2>&1; then
|
||||
dismissed=$((dismissed + 1))
|
||||
fi
|
||||
done
|
||||
|
||||
echo "$dismissed"
|
||||
}
|
||||
|
||||
# ── Preflight checks ─────────────────────────────────────────────────────
|
||||
for cmd in curl jq opencode; do
|
||||
command -v "$cmd" &>/dev/null || die "'$cmd' is required but not found in PATH"
|
||||
@@ -94,7 +177,7 @@ else
|
||||
opencode serve --port "$PORT" --hostname "$HOST" &
|
||||
SERVER_PID=$!
|
||||
OWN_SERVER=true
|
||||
|
||||
|
||||
log "Waiting for server to become healthy (up to ${HEALTH_TIMEOUT}s)..."
|
||||
healthy=false
|
||||
for (( i = 1; i <= HEALTH_TIMEOUT; i++ )); do
|
||||
@@ -110,16 +193,7 @@ else
|
||||
fi
|
||||
|
||||
# ── Create a session ──────────────────────────────────────────────────────
|
||||
log "Creating session..."
|
||||
SESSION_ID=$(
|
||||
curl -sf -X POST "${BASE}/session" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"title":"auto-agents"}' \
|
||||
| jq -r '.id'
|
||||
) || die "Failed to create session"
|
||||
|
||||
[[ -n "$SESSION_ID" && "$SESSION_ID" != "null" ]] || die "Session ID is empty or null"
|
||||
log "Session ID: ${SESSION_ID}"
|
||||
create_session
|
||||
|
||||
# ── send_message ──────────────────────────────────────────────────────────
|
||||
# Sends a JSON body to POST /session/:id/message and blocks until the LLM
|
||||
@@ -158,13 +232,34 @@ log "Initial prompt complete."
|
||||
|
||||
# ── Continue loop ─────────────────────────────────────────────────────────
|
||||
CONT_BODY=$(jq -nc --arg a "$AGENT" '{agent: $a, parts: [{type: "text", text: "continue with your mainloop, monitor the supervisors, keep them alive, and sleep in an infinite loop."}]}')
|
||||
N=0
|
||||
|
||||
while ! $STOP_LOOP; do
|
||||
N=$((N + 1))
|
||||
log "── continue #${N} ──"
|
||||
send_message "$CONT_BODY"
|
||||
log "continue #${N} complete."
|
||||
|
||||
# Check idle-event rate in the last minute
|
||||
idle_count=$(count_idle_events_last_minute)
|
||||
if (( idle_count > MAX_IDLE_PER_MINUTE )); then
|
||||
restart_session
|
||||
continue
|
||||
fi
|
||||
|
||||
log "── iteration #${N} ──"
|
||||
|
||||
# Inspect messages: if a question is waiting for this session, dismiss it;
|
||||
# otherwise issue the standard continue command.
|
||||
dismissed=0
|
||||
if dismissed_raw=$(dismiss_pending_questions "$SESSION_ID"); then
|
||||
dismissed="$dismissed_raw"
|
||||
fi
|
||||
|
||||
if (( dismissed > 0 )); then
|
||||
log "Dismissed ${dismissed} pending question(s)."
|
||||
record_idle_event
|
||||
else
|
||||
send_message "$CONT_BODY"
|
||||
log "continue #${N} complete."
|
||||
record_idle_event
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user