Files
the-nexus/mimo-swarm/scripts/mimo-worker.sh
Claude (Opus 4.6) 63435753e2
Some checks failed
Deploy Nexus / deploy (push) Failing after 3s
Staging Verification Gate / verify-staging (push) Failing after 4s
[claude] Fix mimo swarm worker tool access — add -t terminal,code_execution (#1203) (#1204)
2026-04-11 00:40:46 +00:00

158 lines
5.2 KiB
Bash
Executable File

#!/bin/bash
# Mimo Swarm Worker — One-shot execution
# Receives a prompt file, runs mimo-v2-pro via hermes, handles the git workflow.
#
# Usage: mimo-worker.sh <prompt_file>
# The prompt file contains all instructions for the worker.
set -euo pipefail
PROMPT_FILE="${1:?Usage: mimo-worker.sh <prompt_file>}"
WORKER_ID=$(basename "$PROMPT_FILE" .txt | sed 's/prompt-//')
LOG_DIR="$HOME/.hermes/mimo-swarm/logs"
LOG_FILE="$LOG_DIR/worker-${WORKER_ID}.log"
STATE_DIR="$HOME/.hermes/mimo-swarm/state"
GITEA_URL="https://forge.alexanderwhitestone.com"
TOKEN=$(cat "$HOME/.config/gitea/token")
log() {
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] $*" | tee -a "$LOG_FILE"
}
# Read the prompt
if [ ! -f "$PROMPT_FILE" ]; then
log "ERROR: Prompt file not found: $PROMPT_FILE"
exit 1
fi
PROMPT=$(cat "$PROMPT_FILE")
log "WORKER START: $WORKER_ID"
# Extract repo and issue from prompt
REPO=$(echo "$PROMPT" | grep "^Repository:" | head -1 | awk '{print $2}')
ISSUE_NUM=$(echo "$PROMPT" | grep "^Issue:" | head -1 | awk '{print $2}' | tr -d '#')
LANE=$(echo "$WORKER_ID" | cut -d- -f2)
BRANCH="mimo/${LANE}/issue-${ISSUE_NUM}"
WORK_DIR="/tmp/${WORKER_ID}"
log " Repo: $REPO | Issue: #$ISSUE_NUM | Branch: $BRANCH"
# Clone the repo
mkdir -p "$(dirname "$WORK_DIR")"
if [ -d "$WORK_DIR" ]; then
log " Pulling existing clone..."
cd "$WORK_DIR"
git fetch origin main 2>/dev/null || true
git checkout main 2>/dev/null || git checkout master 2>/dev/null || true
git pull 2>/dev/null || true
else
log " Cloning..."
CLONE_URL="${GITEA_URL}/${REPO}.git"
git clone "$CLONE_URL" "$WORK_DIR" 2>>"$LOG_FILE"
cd "$WORK_DIR"
fi
# Create branch
git checkout -b "$BRANCH" 2>/dev/null || git checkout "$BRANCH"
log " On branch: $BRANCH"
# Run mimo via hermes
log " Dispatching to mimo-v2-pro..."
hermes chat -q "$PROMPT" --provider nous -m xiaomi/mimo-v2-pro --yolo -t terminal,code_execution -Q >>"$LOG_FILE" 2>&1
MIMO_EXIT=$?
log " Mimo exited with code: $MIMO_EXIT"
# Quality gate
log " Running quality gate..."
# Check if there are changes
CHANGES=$(git diff --stat 2>/dev/null || echo "")
STAGED=$(git status --porcelain 2>/dev/null || echo "")
if [ -z "$CHANGES" ] && [ -z "$STAGED" ]; then
log " QUALITY GATE: No changes detected. Worker produced nothing."
# Try to salvage - maybe changes were committed already
COMMITS=$(git log main..HEAD --oneline 2>/dev/null | wc -l | tr -d ' ')
if [ "$COMMITS" -gt 0 ]; then
log " SALVAGE: Found $COMMITS commit(s) on branch. Proceeding to push."
else
log " ABANDON: No commits, no changes. Nothing to salvage."
cd /tmp
rm -rf "$WORK_DIR"
# Write release state
echo "{\"status\":\"abandoned\",\"reason\":\"no_changes\",\"worker\":\"$WORKER_ID\",\"issue\":$ISSUE_NUM}" > "$STATE_DIR/result-${WORKER_ID}.json"
exit 0
fi
else
# Syntax check for Python files
PY_FILES=$(find . -name "*.py" -newer .git/HEAD 2>/dev/null | head -20)
for pyf in $PY_FILES; do
if ! python3 -m py_compile "$pyf" 2>>"$LOG_FILE"; then
log " SYNTAX ERROR in $pyf — attempting fix or committing anyway"
fi
done
# Syntax check for JS files
JS_FILES=$(find . -name "*.js" -newer .git/HEAD 2>/dev/null | head -20)
for jsf in $JS_FILES; do
if ! node --check "$jsf" 2>>"$LOG_FILE"; then
log " SYNTAX ERROR in $jsf — attempting fix or committing anyway"
fi
done
# Diff size check
DIFF_LINES=$(git diff --stat | tail -1 | grep -oP '\d+ insertion' | grep -oP '\d+' || echo "0")
if [ "$DIFF_LINES" -gt 500 ]; then
log " WARNING: Large diff ($DIFF_LINES insertions). Committing but flagging for review."
fi
# Commit
git add -A
COMMIT_MSG="fix: $(echo "$PROMPT" | grep '^Title:' | sed 's/^Title: //') (closes #${ISSUE_NUM})"
git commit -m "$COMMIT_MSG" 2>>"$LOG_FILE" || log " Nothing to commit (already clean)"
fi
# Push
log " Pushing branch..."
PUSH_OUTPUT=$(git push origin "$BRANCH" 2>&1) || {
log " Push failed, trying force push..."
git push -f origin "$BRANCH" 2>>"$LOG_FILE" || log " Push failed completely"
}
log " Pushed: $PUSH_OUTPUT"
# Create PR
log " Creating PR..."
PR_TITLE="fix: $(echo "$PROMPT" | grep '^Title:' | sed 's/^Title: //')"
PR_BODY="Closes #${ISSUE_NUM}
Automated by mimo-v2-pro swarm worker.
Worker: ${WORKER_ID}"
PR_RESPONSE=$(curl -s -X POST "${GITEA_URL}/api/v1/repos/${REPO}/pulls" \
-H "Authorization: token ${TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"title\":\"${PR_TITLE}\",\"head\":\"${BRANCH}\",\"base\":\"main\",\"body\":\"${PR_BODY}\"}" 2>>"$LOG_FILE")
PR_NUM=$(echo "$PR_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin).get('number','?'))" 2>/dev/null || echo "?")
log " PR created: #${PR_NUM}"
# Clean up
cd /tmp
# Keep work dir for debugging, clean later
# Write result
cat > "$STATE_DIR/result-${WORKER_ID}.json" <<EOF
{
"status": "completed",
"worker": "$WORKER_ID",
"repo": "$REPO",
"issue": $ISSUE_NUM,
"branch": "$BRANCH",
"pr": $PR_NUM,
"mimo_exit": $MIMO_EXIT,
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
log "WORKER COMPLETE: $WORKER_ID → PR #${PR_NUM}"