fix: use sh -c with inline release-slot.sh for fire-and-forget delegation #47

Merged
shoko merged 3 commits from fix/issue-44-release-agent-slot into main 2026-03-31 14:53:14 +02:00
Showing only changes of commit 1c4d076d84 - Show all commits

View File

@@ -58,7 +58,6 @@ run_with_limit() {
) & ) &
disown disown
} }
>>>>>>> Stashed changes
usage() { usage() {
cat << 'EOF' cat << 'EOF'
@@ -68,7 +67,8 @@ Usage:
kugetsu init [--force] Initialize base + pm-agent sessions (requires TTY) kugetsu init [--force] Initialize base + pm-agent sessions (requires TTY)
kugetsu start <issue-ref> <message> [--debug] Start task for issue (forks base session) kugetsu start <issue-ref> <message> [--debug] Start task for issue (forks base session)
kugetsu continue <issue-ref> [message] [--debug] Continue existing task for issue kugetsu continue <issue-ref> [message] [--debug] Continue existing task for issue
kugetsu delegate <message> Send message to PM agent kugetsu delegate <message> Send message to PM agent (fire-and-forget)
kugetsu logs [n] Show recent delegation logs (default: 10)
kugetsu status Check kugetsu initialization status kugetsu status Check kugetsu initialization status
kugetsu doctor [--fix] Diagnose and fix kugetsu issues kugetsu doctor [--fix] Diagnose and fix kugetsu issues
kugetsu notify [list|clear] Show or clear notifications kugetsu notify [list|clear] Show or clear notifications
@@ -90,7 +90,10 @@ Commands:
Requires pm-agent to be running (created by init). Requires pm-agent to be running (created by init).
continue Continue work on existing issue session. continue Continue work on existing issue session.
delegate Send message to PM agent for task coordination. delegate Send message to PM agent for task coordination.
PM context is loaded once at init time. Fire-and-forget: returns immediately, runs in background.
Use 'kugetsu logs' to check output.
logs Show recent delegation logs.
Default: 10 most recent. Use 'kugetsu logs 20' for more.
status Check if kugetsu is initialized and PM agent is active. status Check if kugetsu is initialized and PM agent is active.
doctor Diagnose kugetsu issues. Use --fix to attempt repairs. doctor Diagnose kugetsu issues. Use --fix to attempt repairs.
notify Show or clear notifications from PM agent. notify Show or clear notifications from PM agent.
@@ -116,6 +119,8 @@ Examples:
kugetsu init kugetsu init
kugetsu status kugetsu status
kugetsu delegate "work on issue #5" kugetsu delegate "work on issue #5"
kugetsu logs
kugetsu logs 20
kugetsu doctor kugetsu doctor
kugetsu doctor --fix kugetsu doctor --fix
kugetsu notify list kugetsu notify list
@@ -128,6 +133,26 @@ EOF
ensure_dirs() { ensure_dirs() {
mkdir -p "$SESSIONS_DIR" mkdir -p "$SESSIONS_DIR"
[ -f "$AGENT_COUNT_FILE" ] || echo 0 > "$AGENT_COUNT_FILE"
# Install release-slot.sh if not exists
local release_script="$KUGETSU_DIR/release-slot.sh"
if [ ! -f "$release_script" ]; then
cat > "$release_script" << 'RELEASESLOT'
#!/bin/bash
KUGETSU_DIR="${KUGETSU_DIR:-$HOME/.kugetsu}"
AGENT_COUNT_FILE="$KUGETSU_DIR/.agent_count"
AGENT_LOCK_FILE="$KUGETSU_DIR/.agent_lock"
(
flock -w 1 200 || true
count=$(cat "$AGENT_COUNT_FILE" 2>/dev/null || echo 0)
if [ "$count" -gt 0 ]; then
echo $((count - 1)) > "$AGENT_COUNT_FILE"
fi
) 200>"$AGENT_LOCK_FILE"
RELEASESLOT
chmod +x "$release_script"
fi
} }
ensure_worktree_dir() { ensure_worktree_dir() {
@@ -545,7 +570,31 @@ cmd_delegate() {
exit 1 exit 1
fi fi
opencode run --continue --session "$pm_session" "$message" 2>&1 mkdir -p "$LOGS_DIR"
local log_file="$LOGS_DIR/delegate-$(date +%s).log"
if ! acquire_agent_slot; then
echo "Error: Max concurrent agents ($MAX_CONCURRENT_AGENTS) reached. Try again later." >&2
exit 1
fi
nohup sh -c "opencode run --continue --session '$pm_session' '$message' >> '$log_file' 2>&1; ~/.kugetsu/release-slot.sh" > /dev/null 2>&1 &
disown
echo "Delegated to PM agent (logged to $(basename "$log_file"))"
}
cmd_logs() {
local count="${1:-10}"
if [ ! -d "$LOGS_DIR" ]; then
echo "No logs found."
return
fi
# Log rotation: delete logs older than 7 days
find "$LOGS_DIR" -type f -mtime +7 -delete 2>/dev/null
ls -lt "$LOGS_DIR" | head -$((count + 1)) | tail -$count | while read line; do
echo "$line"
done
} }
cmd_doctor() { cmd_doctor() {
@@ -821,11 +870,19 @@ cmd_start() {
local before_set="${before_sessions//$'\n'/|}" local before_set="${before_sessions//$'\n'/|}"
echo "Forking session for '$issue_ref'..." echo "Forking session for '$issue_ref'..."
if ! acquire_agent_slot; then
echo "Error: Max concurrent agents ($MAX_CONCURRENT_AGENTS) reached. Try again later." >&2
remove_worktree_for_issue "$issue_ref"
exit 1
fi
trap release_agent_slot EXIT
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1 | tee "$SESSIONS_DIR/$session_file.debug.log" opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1 | tee "$SESSIONS_DIR/$session_file.debug.log"
else else
opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1 opencode run --fork --session "$base_session_id" "$message" --workdir "$worktree_path" 2>&1
fi fi
release_agent_slot
trap - EXIT
local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort) local after_sessions=$(opencode session list 2>/dev/null | grep -oP '^ses_\w+' | sort)
local new_session_id="" local new_session_id=""
@@ -894,6 +951,11 @@ cmd_continue() {
local worktree_path=$(python3 -c "import json; print(json.load(open('$session_path')).get('worktree_path', ''))" 2>/dev/null || echo "") local worktree_path=$(python3 -c "import json; print(json.load(open('$session_path')).get('worktree_path', ''))" 2>/dev/null || echo "")
echo "Continuing session for '$session_name'..." echo "Continuing session for '$session_name'..."
if ! acquire_agent_slot; then
echo "Error: Max concurrent agents ($MAX_CONCURRENT_AGENTS) reached. Try again later." >&2
exit 1
fi
trap release_agent_slot EXIT
if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then if [ -n "$worktree_path" ] && [ -d "$worktree_path" ]; then
echo "Using worktree: $worktree_path" echo "Using worktree: $worktree_path"
if [ "$DEBUG_MODE" = true ]; then if [ "$DEBUG_MODE" = true ]; then
@@ -908,6 +970,8 @@ cmd_continue() {
opencode run --continue --session "$opencode_session_id" "$message" opencode run --continue --session "$opencode_session_id" "$message"
fi fi
fi fi
release_agent_slot
trap - EXIT
} }
cmd_list() { cmd_list() {
@@ -1144,6 +1208,10 @@ main() {
delegate) delegate)
cmd_delegate "$@" cmd_delegate "$@"
;; ;;
logs)
shift
cmd_logs "$@"
;;
status) status)
cmd_status cmd_status
;; ;;