Skip to content

Commit e002357

Browse files
authored
Merge pull request #589 from Fr-e-d/contrib/sync-1782569517
sync: update 3 file(s) in core/
2 parents 364eb36 + c04e88e commit e002357

3 files changed

Lines changed: 134 additions & 75 deletions

File tree

.gaai/core/scripts/daemon-start.sh

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,28 @@ STOP_DRAIN_TIMEOUT="${GAAI_STOP_DRAIN_TIMEOUT:-600}"
7979
# ── Helpers ───────────────────────────────────────────────────────────────
8080

8181
daemon_is_running() {
82-
[[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null
82+
if [[ -f "$PID_FILE" ]] && kill -0 "$(cat "$PID_FILE")" 2>/dev/null; then
83+
return 0
84+
fi
85+
if command -v tmux &>/dev/null && tmux has-session -t gaai-daemon 2>/dev/null; then
86+
local tmux_pid
87+
tmux_pid=$(tmux list-panes -t gaai-daemon -F '#{pane_pid}' 2>/dev/null | head -1 || echo "")
88+
[[ -n "$tmux_pid" ]] && kill -0 "$tmux_pid" 2>/dev/null
89+
return $?
90+
fi
91+
return 1
8392
}
8493

8594
get_pid() {
86-
[[ -f "$PID_FILE" ]] && cat "$PID_FILE" || echo ""
95+
if [[ -f "$PID_FILE" ]]; then
96+
cat "$PID_FILE"
97+
return
98+
fi
99+
if command -v tmux &>/dev/null && tmux has-session -t gaai-daemon 2>/dev/null; then
100+
tmux list-panes -t gaai-daemon -F '#{pane_pid}' 2>/dev/null | head -1 || echo ""
101+
return
102+
fi
103+
echo ""
87104
}
88105

89106
# ── Parse action ──────────────────────────────────────────────────────────
@@ -441,6 +458,11 @@ do_start() {
441458
# Admin fallback (free-tier opt-in) — when --auto fails branch_protection_missing,
442459
# fall back to gh pr merge --admin --squash. Trust-arc opt-in, default off.
443460
[[ -n "${GAAI_AUTO_MERGE_ADMIN_FALLBACK:-}" ]] && tmux_env_args+=(-e "GAAI_AUTO_MERGE_ADMIN_FALLBACK=${GAAI_AUTO_MERGE_ADMIN_FALLBACK}")
461+
[[ -n "${GAAI_DAEMON_EXECUTOR:-}" ]] && tmux_env_args+=(-e "GAAI_DAEMON_EXECUTOR=${GAAI_DAEMON_EXECUTOR}")
462+
[[ -n "${GAAI_CODEX_MODEL:-}" ]] && tmux_env_args+=(-e "GAAI_CODEX_MODEL=${GAAI_CODEX_MODEL}")
463+
[[ -n "${GAAI_CODEX_SANDBOX:-}" ]] && tmux_env_args+=(-e "GAAI_CODEX_SANDBOX=${GAAI_CODEX_SANDBOX}")
464+
[[ -n "${GAAI_CODEX_EPHEMERAL:-}" ]] && tmux_env_args+=(-e "GAAI_CODEX_EPHEMERAL=${GAAI_CODEX_EPHEMERAL}")
465+
[[ -n "${GAAI_CODEX_IGNORE_USER_CONFIG:-}" ]] && tmux_env_args+=(-e "GAAI_CODEX_IGNORE_USER_CONFIG=${GAAI_CODEX_IGNORE_USER_CONFIG}")
444466
[[ -n "${GAAI_DAEMON_HOME:-}" ]] && tmux_env_args+=(-e "GAAI_DAEMON_HOME=${GAAI_DAEMON_HOME}")
445467
[[ -n "${GAAI_REPO_ROOT:-}" ]] && tmux_env_args+=(-e "GAAI_REPO_ROOT=${GAAI_REPO_ROOT}")
446468
tmux new-session -d -s gaai-daemon ${tmux_env_args[@]+"${tmux_env_args[@]}"} "$daemon_cmd"

.gaai/core/scripts/delivery-daemon.sh

Lines changed: 109 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -583,11 +583,25 @@ if ! command -v python3 &>/dev/null; then
583583
exit 1
584584
fi
585585

586-
if ! command -v claude &>/dev/null; then
587-
echo -e "${RED}ERROR: claude CLI not found in PATH${NC}"
588-
echo "Install: https://docs.anthropic.com/en/docs/claude-code"
589-
exit 1
590-
fi
586+
case "${GAAI_DAEMON_EXECUTOR:-claude}" in
587+
claude)
588+
if ! command -v claude &>/dev/null; then
589+
echo -e "${RED}ERROR: claude CLI not found in PATH${NC}"
590+
echo "Install: https://docs.anthropic.com/en/docs/claude-code"
591+
exit 1
592+
fi
593+
;;
594+
codex)
595+
if ! command -v codex &>/dev/null; then
596+
echo -e "${RED}ERROR: codex CLI not found in PATH${NC}"
597+
exit 1
598+
fi
599+
;;
600+
*)
601+
echo -e "${RED}ERROR: unknown GAAI_DAEMON_EXECUTOR='${GAAI_DAEMON_EXECUTOR:-}' (expected claude or codex)${NC}"
602+
exit 1
603+
;;
604+
esac
591605

592606
if [[ ! -f "$SCHEDULER" ]]; then
593607
echo -e "${RED}ERROR: backlog-scheduler.sh not found at $SCHEDULER${NC}"
@@ -3223,49 +3237,53 @@ if [[ -n "\${_BINDING_JWT}" ]]; then
32233237
_MCP_HEADER_ARGS=(--header "X-GAAI-Authorized-Workspaces:\${_BINDING_JWT}")
32243238
fi
32253239
3226-
# --output-format stream-json streams NDJSON events in real-time, so:
3227-
# - tee updates the log file continuously (natural heartbeat for daemon monitor)
3228-
# - tail -f shows progress in real-time
3229-
# Dispatch wall-clock cap: prefer gtimeout (macOS: brew install coreutils) → timeout (BSD) →
3230-
# no binary = MAX_TURNS flag cap + daemon heartbeat watchdog are the liveness guards.
3240+
# --output-format stream-json / codex --json stream events in real time, so tee
3241+
# updates the log continuously (natural heartbeat for daemon monitor).
3242+
_AGENT_PROMPT="\${DELIVERY_PROMPT}
3243+
3244+
Deliver story: $story_id"
3245+
3246+
_TIMEOUT_PREFIX=()
32313247
if command -v gtimeout &>/dev/null; then
3232-
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3233-
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3234-
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3235-
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3236-
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3237-
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3238-
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3239-
gtimeout "$DELIVERY_TIMEOUT" claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${DELIVERY_PROMPT}
3240-
3241-
Deliver story: $story_id" 2>&1 | tee -a "$delivery_log"
3242-
EXIT_CODE=\${PIPESTATUS[0]}
3248+
_TIMEOUT_PREFIX=(gtimeout "$DELIVERY_TIMEOUT")
32433249
elif command -v timeout &>/dev/null; then
3244-
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3245-
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3246-
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3247-
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3248-
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3249-
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3250-
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3251-
timeout "$DELIVERY_TIMEOUT" claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${DELIVERY_PROMPT}
3252-
3253-
Deliver story: $story_id" 2>&1 | tee -a "$delivery_log"
3254-
EXIT_CODE=\${PIPESTATUS[0]}
3255-
else
3256-
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3257-
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3258-
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3259-
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3260-
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3261-
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3262-
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3263-
claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${DELIVERY_PROMPT}
3264-
3265-
Deliver story: $story_id" 2>&1 | tee -a "$delivery_log"
3266-
EXIT_CODE=\${PIPESTATUS[0]}
3250+
_TIMEOUT_PREFIX=(timeout "$DELIVERY_TIMEOUT")
32673251
fi
32683252
3253+
case "\${GAAI_DAEMON_EXECUTOR:-claude}" in
3254+
claude)
3255+
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3256+
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3257+
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3258+
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3259+
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3260+
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3261+
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3262+
"\${_TIMEOUT_PREFIX[@]}" claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${_AGENT_PROMPT}" 2>&1 | tee -a "$delivery_log"
3263+
EXIT_CODE=\${PIPESTATUS[0]}
3264+
;;
3265+
codex)
3266+
_CODEX_SANDBOX="\${GAAI_CODEX_SANDBOX:-workspace-write}"
3267+
[[ "\$_CODEX_SANDBOX" == "danger" ]] && _CODEX_SANDBOX="danger-full-access"
3268+
_CODEX_ARGS=(exec --json --cd "$PROJECT_DIR" --sandbox "\$_CODEX_SANDBOX")
3269+
[[ "\${GAAI_CODEX_EPHEMERAL:-1}" != "0" ]] && _CODEX_ARGS+=(--ephemeral)
3270+
[[ "\${GAAI_CODEX_IGNORE_USER_CONFIG:-0}" == "1" ]] && _CODEX_ARGS+=(--ignore-user-config)
3271+
[[ -n "\${GAAI_CODEX_MODEL:-}" ]] && _CODEX_ARGS+=(--model "\${GAAI_CODEX_MODEL}")
3272+
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3273+
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3274+
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3275+
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3276+
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3277+
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3278+
"\${_TIMEOUT_PREFIX[@]}" codex "\${_CODEX_ARGS[@]}" "\${_AGENT_PROMPT}" 2>&1 | tee -a "$delivery_log"
3279+
EXIT_CODE=\${PIPESTATUS[0]}
3280+
;;
3281+
*)
3282+
echo "ERROR: unknown GAAI_DAEMON_EXECUTOR='\${GAAI_DAEMON_EXECUTOR:-}'" >&2
3283+
EXIT_CODE=2
3284+
;;
3285+
esac
3286+
32693287
echo ""
32703288
echo "================================================================"
32713289
echo " Delivery ended: $story_id"
@@ -3898,38 +3916,52 @@ if [[ -n "\${_BINDING_JWT}" ]]; then
38983916
_MCP_HEADER_ARGS=(--header "X-GAAI-Authorized-Workspaces:\${_BINDING_JWT}")
38993917
fi
39003918
3901-
# Print mode (-p): claude processes the prompt and exits, freeing the daemon slot.
3902-
# --dangerously-skip-permissions handles tool approval (required for headless).
3903-
# --output-format stream-json streams NDJSON events in real-time, so:
3904-
# - tee updates the log file continuously (natural heartbeat for daemon monitor)
3905-
# - tail -f shows progress in real-time
3919+
# Claude remains the default executor. Codex is opt-in via GAAI_DAEMON_EXECUTOR=codex.
3920+
_AGENT_PROMPT="\${DELIVERY_PROMPT}
3921+
3922+
Deliver story: $story_id"
39063923
3924+
_TIMEOUT_PREFIX=()
39073925
if command -v gtimeout &>/dev/null; then
3908-
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3909-
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3910-
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3911-
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3912-
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3913-
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3914-
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3915-
gtimeout "$DELIVERY_TIMEOUT" claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${DELIVERY_PROMPT}
3916-
3917-
Deliver story: $story_id" 2>&1 | tee -a "$delivery_log"
3918-
EXIT_CODE=\${PIPESTATUS[0]}
3919-
else
3920-
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3921-
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3922-
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3923-
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3924-
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3925-
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3926-
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3927-
claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${DELIVERY_PROMPT}
3928-
3929-
Deliver story: $story_id" 2>&1 | tee -a "$delivery_log"
3930-
EXIT_CODE=\${PIPESTATUS[0]}
3926+
_TIMEOUT_PREFIX=(gtimeout "$DELIVERY_TIMEOUT")
3927+
elif command -v timeout &>/dev/null; then
3928+
_TIMEOUT_PREFIX=(timeout "$DELIVERY_TIMEOUT")
39313929
fi
39323930
3931+
case "\${GAAI_DAEMON_EXECUTOR:-claude}" in
3932+
claude)
3933+
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3934+
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3935+
ANTHROPIC_BASE_URL="\${ANTHROPIC_BASE_URL:-}" \
3936+
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3937+
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3938+
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3939+
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3940+
"\${_TIMEOUT_PREFIX[@]}" claude $CLAUDE_FLAGS "\${_MCP_HEADER_ARGS[@]}" -p "\${_AGENT_PROMPT}" 2>&1 | tee -a "$delivery_log"
3941+
EXIT_CODE=\${PIPESTATUS[0]}
3942+
;;
3943+
codex)
3944+
_CODEX_SANDBOX="\${GAAI_CODEX_SANDBOX:-workspace-write}"
3945+
[[ "\$_CODEX_SANDBOX" == "danger" ]] && _CODEX_SANDBOX="danger-full-access"
3946+
_CODEX_ARGS=(exec --json --cd "$PROJECT_DIR" --sandbox "\$_CODEX_SANDBOX")
3947+
[[ "\${GAAI_CODEX_EPHEMERAL:-1}" != "0" ]] && _CODEX_ARGS+=(--ephemeral)
3948+
[[ "\${GAAI_CODEX_IGNORE_USER_CONFIG:-0}" == "1" ]] && _CODEX_ARGS+=(--ignore-user-config)
3949+
[[ -n "\${GAAI_CODEX_MODEL:-}" ]] && _CODEX_ARGS+=(--model "\${GAAI_CODEX_MODEL}")
3950+
GAAI_WORKSPACE_ID="\${GAAI_WORKSPACE_ID:-}" \
3951+
GAAI_ORG_ID="\${GAAI_ORG_ID:-}" \
3952+
GAAI_IMPL_BASE_URL="\${GAAI_IMPL_BASE_URL:-}" \
3953+
GAAI_IMPL_AUTH_TOKEN="\${GAAI_IMPL_AUTH_TOKEN:-}" \
3954+
GAAI_IMPL_MODEL="\${GAAI_IMPL_MODEL:-}" \
3955+
GAAI_DELIVERY_LOG_FILE="$LOG_DIR/${story_id}.log" \
3956+
"\${_TIMEOUT_PREFIX[@]}" codex "\${_CODEX_ARGS[@]}" "\${_AGENT_PROMPT}" 2>&1 | tee -a "$delivery_log"
3957+
EXIT_CODE=\${PIPESTATUS[0]}
3958+
;;
3959+
*)
3960+
echo "ERROR: unknown GAAI_DAEMON_EXECUTOR='\${GAAI_DAEMON_EXECUTOR:-}'" >&2
3961+
EXIT_CODE=2
3962+
;;
3963+
esac
3964+
39333965
# ── Agent exit signal (DEC-72 wrapper-side audit trail) ─────────────────────
39343966
EXIT_TS=\$(date +%s)
39353967
DURATION_MS=\$(( (EXIT_TS - PREFLIGHT_TS) * 1000 ))
@@ -4237,11 +4269,15 @@ shutdown() {
42374269
trap shutdown SIGINT SIGTERM
42384270

42394271
# ── Save config for monitor ──────────────────────────────────────────────
4272+
DISPLAY_MODEL="$CLAUDE_MODEL"
4273+
if [[ "${GAAI_DAEMON_EXECUTOR:-claude}" == "codex" ]]; then
4274+
DISPLAY_MODEL="${GAAI_CODEX_MODEL:-codex}"
4275+
fi
42404276
cat > "$LOCK_DIR/.daemon-config" << EOF
42414277
BRANCH="$TARGET_BRANCH"
42424278
INTERVAL="$POLL_INTERVAL"
42434279
CONCURRENT="$MAX_CONCURRENT"
4244-
MODEL="$CLAUDE_MODEL"
4280+
MODEL="$DISPLAY_MODEL"
42454281
LAUNCHER="$LAUNCHER"
42464282
SKIP_PERMS="$SKIP_PERMISSIONS"
42474283
MAX_TURNS="$MAX_TURNS"

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
## [Unreleased]
1111

1212
### Changed
13+
- fix: support codex executor in bash daemon
1314
- fix: show codex monitor activity
1415
- fix: show codex monitor activity
1516
- fix: bake REPO_ROOT into the generated delivery wrapper (worktree nesting)

0 commit comments

Comments
 (0)