diff --git a/swarm_framework/bootstrap.sh b/swarm_framework/bootstrap.sh index 955defa..58ec526 100755 --- a/swarm_framework/bootstrap.sh +++ b/swarm_framework/bootstrap.sh @@ -11,7 +11,24 @@ cleanup() { echo "Enforcing smooth start (cleaning up previous state)..." - tmux kill-session -t $SESSION_NAME 2>/dev/null + + # Kill all sessions in the group or containing the session name + tmux list-sessions -F '#{session_name} #{session_group}' 2>/dev/null | while read -r s g; do + if [ "$g" = "$SESSION_NAME" ] || [[ "$s" == *"$SESSION_NAME"* ]]; then + tmux kill-session -t "$s" 2>/dev/null + fi + done + + # Kill all processes with CWD under this directory (leaked subagents) + # Only kill language_server (jetski) and server.par (codemind) to avoid killing ourselves! + find /proc -maxdepth 2 -name cwd -exec ls -l {} + 2>/dev/null | grep "$SCRIPT_DIR" | while read -r line; do + pid=$(echo "$line" | awk -F/ '{print $3}') + cmd=$(ps -p "$pid" -o comm= 2>/dev/null) + if [[ "$cmd" == *"language_server"* ]] || [[ "$cmd" == *"server.par"* ]]; then + kill -9 "$pid" 2>/dev/null + fi + done + rm -f "$SCRIPT_DIR/comms/requests/"*.json echo "Cleanup complete." } @@ -70,7 +87,11 @@ echo " tmux attach -t $SESSION_NAME:orchestrator" echo "Or check the file: $SCRIPT_DIR/orchestrator.log" echo "" -echo "To view all windows:" +echo "To view Master and Grid independently in two terminals:" +echo " Run this in the second terminal to open the grid automatically:" +echo " tmux new-session -t $SESSION_NAME -s ${SESSION_NAME}_view2 \\; select-window -t grid" +echo "" +echo "To view all windows in one linked session:" echo " tmux attach -t $SESSION_NAME" echo "" echo "To stop the swarm and cleanup:" diff --git a/swarm_framework/orchestrator.py b/swarm_framework/orchestrator.py index 18e19a1..785b9d8 100644 --- a/swarm_framework/orchestrator.py +++ b/swarm_framework/orchestrator.py @@ -2,6 +2,7 @@ import time import json import subprocess +import shlex # Self-contained paths relative to this script BASE_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -129,12 +130,35 @@ state = AGENT_STATE.setdefault(target, {}) state["last_cmd_time"] = time.time() + # Capture output before sending to detect if it starts working + cap_cmd = f"tmux capture-pane -p -t {SESSION_NAME}:{target}" + try: + result = subprocess.run(cap_cmd, shell=True, capture_output=True, text=True, check=True) + output_before = result.stdout + except Exception: + output_before = "" + # Send keys - cmd = f"tmux send-keys -t {SESSION_NAME}:{target} \"{prompt}\" C-m" + quoted_prompt = shlex.quote(prompt) + cmd = f"tmux send-keys -t {SESSION_NAME}:{target} {quoted_prompt} C-m" subprocess.run(cmd, shell=True, check=True) - # Wait for agent to process - time.sleep(5) + # Check shortly if agent started working + time.sleep(1) + try: + result = subprocess.run(cap_cmd, shell=True, capture_output=True, text=True, check=True) + output_after = result.stdout + except Exception: + output_after = "" + + if output_before == output_after: + print(f"Agent {target} seems stuck, sending extra Enter...") + cmd = f"tmux send-keys -t {SESSION_NAME}:{target} C-m" + subprocess.run(cmd, shell=True, check=True) + time.sleep(1) # Wait a bit more + + # Wait for agent to process further + time.sleep(3) # Capture pane for response cap_cmd = f"tmux capture-pane -p -t {SESSION_NAME}:{target}"