From ddd57f8034a88419f72aabc2b5b705d31466dc66 Mon Sep 17 00:00:00 2001 From: NagyVikt Date: Sat, 16 May 2026 11:45:11 +0200 Subject: [PATCH] refactor(codex-fleet): extract shared bash helpers into lib/ Move duplicated helpers out of fleet-tick.sh, cap-swap-daemon.sh, and cap-probe.sh into two sourced libraries: - scripts/codex-fleet/lib/agents.sh: derive_aid (and email_to_id alias), the canonical email -> agent-id derivation. Replaces the inline bash copy in fleet-tick.sh and the two python3 copies in cap-swap-daemon.sh and cap-probe.sh. Functionally identical (verified against alice@gmail.com, bob@magnoliavilag.hu, carol@gitguardex.com, dave@pipacsclub.org, eve+x@example.co.uk). Documents the cross-language sync requirement with rust/fleet-data/src/fleet.rs::derive_agent_id. - scripts/codex-fleet/lib/ui-helpers.sh: strip_ansi, ios_visible_len, pct_color, ios_status_chip_label. Pulled out of fleet-tick.sh. Both libs use a __CODEX_FLEET_LIB_*_SH guard so double-sourcing is a no-op and are set -u safe. Functions only, no top-level side effects. Scripts source them via "$(dirname "${BASH_SOURCE[0]}")/lib/..." so invocation from any cwd resolves correctly. Co-Authored-By: Claude Opus 4.7 (1M context) --- scripts/codex-fleet/cap-probe.sh | 9 +---- scripts/codex-fleet/cap-swap-daemon.sh | 9 +---- scripts/codex-fleet/fleet-tick.sh | 56 +------------------------- scripts/codex-fleet/lib/agents.sh | 26 ++++++++++++ scripts/codex-fleet/lib/ui-helpers.sh | 47 +++++++++++++++++++++ 5 files changed, 77 insertions(+), 70 deletions(-) create mode 100644 scripts/codex-fleet/lib/agents.sh create mode 100644 scripts/codex-fleet/lib/ui-helpers.sh diff --git a/scripts/codex-fleet/cap-probe.sh b/scripts/codex-fleet/cap-probe.sh index f86e0a4..f3822ab 100755 --- a/scripts/codex-fleet/cap-probe.sh +++ b/scripts/codex-fleet/cap-probe.sh @@ -37,14 +37,7 @@ mkdir -p "$(dirname "$LOG")" ts() { date +%H:%M:%S; } log() { echo "[$(ts)] $*" >> "$LOG"; } -email_to_id() { - python3 -c " -import sys -e=sys.argv[1]; part,dom=e.split('@',1); dom=dom.split('.',1)[0] -m={'magnoliavilag':'magnolia','gitguardex':'gg','pipacsclub':'pipacs'} -print(f'{part}-{m.get(dom,dom)}') -" "$1" -} +source "$(dirname "${BASH_SOURCE[0]}")/lib/agents.sh" # Returns one of: healthy | capped | stale (re-probe). # Sets globals VERDICT, UNTIL_TEXT, UNTIL_EPOCH for the caller. diff --git a/scripts/codex-fleet/cap-swap-daemon.sh b/scripts/codex-fleet/cap-swap-daemon.sh index aa8eda1..2735545 100755 --- a/scripts/codex-fleet/cap-swap-daemon.sh +++ b/scripts/codex-fleet/cap-swap-daemon.sh @@ -36,14 +36,7 @@ mkdir -p "$(dirname "$LOG")" "$(dirname "$STATUS_FILE")" "$STATE" ts() { date +%H:%M:%S; } log() { echo "[$(ts)] $*" | tee -a "$LOG"; } -email_to_id() { - python3 -c " -import sys -e=sys.argv[1]; part,dom=e.split('@',1); dom=dom.split('.',1)[0] -m={'magnoliavilag':'magnolia','gitguardex':'gg','pipacsclub':'pipacs'} -print(f'{part}-{m.get(dom,dom)}') -" "$1" -} +source "$(dirname "${BASH_SOURCE[0]}")/lib/agents.sh" # Emails currently assigned to fleet panes (from /proc//environ of each pane's codex) current_emails() { diff --git a/scripts/codex-fleet/fleet-tick.sh b/scripts/codex-fleet/fleet-tick.sh index 2f352c2..64d2796 100755 --- a/scripts/codex-fleet/fleet-tick.sh +++ b/scripts/codex-fleet/fleet-tick.sh @@ -36,21 +36,7 @@ declare -a FLEET_EMAILS=() declare -A IS_CURRENT CURRENT_EMAIL="" -# Canonical email→id derivation. Mirrors: -# scripts/codex-fleet/cap-swap-daemon.sh::email_to_id -# scripts/codex-fleet/full-bringup.sh (Python id map) -derive_aid() { - local email="$1" part dom - part="${email%%@*}" - dom="${email#*@}" - dom="${dom%%.*}" - case "$dom" in - magnoliavilag) dom=magnolia ;; - gitguardex) dom=gg ;; - pipacsclub) dom=pipacs ;; - esac - printf '%s-%s' "$part" "$dom" -} +source "$(dirname "${BASH_SOURCE[0]}")/lib/agents.sh" # Sub-task evidence files scored by subtask_progress_pct for fractional progress. SUB_EVIDENCE=( @@ -112,15 +98,7 @@ IOS_CHIP_LEFT="◖" IOS_CHIP_RIGHT="◗" IOS_STATUS_CHIP_WIDTH=9 -strip_ansi() { - sed -E $'s/\x1B\\[[0-9;]*m//g' <<<"${1:-}" -} - -ios_visible_len() { - local clean - clean=$(strip_ansi "${1:-}") - printf '%d' "${#clean}" -} +source "$(dirname "${BASH_SOURCE[0]}")/lib/ui-helpers.sh" ios_card_top() { local title="${1:-}" @@ -158,20 +136,6 @@ ios_card_blank() { ios_card_row "" "${1:-$IOS_CARD_WIDTH}" } -# Pick gradient color by percentage int -pct_color() { - local n="$1" - [[ "$n" =~ ^[0-9]+$ ]] || { printf '%s' "$DIM"; return; } - if (( n >= 90 )); then printf '%s' "$GRAD6" - elif (( n >= 75 )); then printf '%s' "$GRAD5" - elif (( n >= 60 )); then printf '%s' "$GRAD4" - elif (( n >= 45 )); then printf '%s' "$GRAD3" - elif (( n >= 30 )); then printf '%s' "$GRAD2" - elif (( n >= 15 )); then printf '%s' "$GRAD1" - else printf '%s' "$GRAD0" - fi -} - # Tiny block-spark for a percentage (▁..█). Kept for older tests; new UI uses # ios_progress_rail below. pct_spark() { @@ -249,22 +213,6 @@ ios_progress_rail() { printf '%b▕%b%s%b%s%b▏%b' "$IOS_GRAY2" "$color" "$fill" "$IOS_GRAY6" "$empty" "$IOS_GRAY2" "$R" } -ios_status_chip_label() { - local kind="${1:-idle}" - local raw pad_len pad - case "$kind" in - run|running) raw="● running" ;; - work|working|busy) raw="● working" ;; - exhaust|exhausted|capped) raw="⚠ exhaust" ;; - limit|limited|rate_limited|rate-limited) raw="◍ limited" ;; - idle|*) raw="◌ idle" ;; - esac - pad_len=$(( IOS_STATUS_CHIP_WIDTH - ${#raw} )) - (( pad_len < 0 )) && pad_len=0 - printf -v pad '%*s' "$pad_len" "" - printf '%s%s' "$raw" "$pad" -} - ios_status_chip_bg() { local kind="${1:-idle}" case "$kind" in diff --git a/scripts/codex-fleet/lib/agents.sh b/scripts/codex-fleet/lib/agents.sh new file mode 100644 index 0000000..34ef73a --- /dev/null +++ b/scripts/codex-fleet/lib/agents.sh @@ -0,0 +1,26 @@ +# shellcheck shell=bash +# MUST stay in sync with rust/fleet-data/src/fleet.rs::derive_agent_id +# (around lines 105-118). Any change to the domain-stem alias map or the +# email parsing semantics here must be mirrored there. + +if [[ -n "${__CODEX_FLEET_LIB_AGENTS_SH:-}" ]]; then + return 0 2>/dev/null || exit 0 +fi +__CODEX_FLEET_LIB_AGENTS_SH=1 + +derive_aid() { + local email="${1:-}" part dom + part="${email%%@*}" + dom="${email#*@}" + dom="${dom%%.*}" + case "$dom" in + magnoliavilag) dom=magnolia ;; + gitguardex) dom=gg ;; + pipacsclub) dom=pipacs ;; + esac + printf '%s-%s' "$part" "$dom" +} + +email_to_id() { + derive_aid "$@" +} diff --git a/scripts/codex-fleet/lib/ui-helpers.sh b/scripts/codex-fleet/lib/ui-helpers.sh new file mode 100644 index 0000000..ceb34b6 --- /dev/null +++ b/scripts/codex-fleet/lib/ui-helpers.sh @@ -0,0 +1,47 @@ +# shellcheck shell=bash + +if [[ -n "${__CODEX_FLEET_LIB_UI_HELPERS_SH:-}" ]]; then + return 0 2>/dev/null || exit 0 +fi +__CODEX_FLEET_LIB_UI_HELPERS_SH=1 + +: "${IOS_STATUS_CHIP_WIDTH:=9}" + +strip_ansi() { + sed -E $'s/\x1B\\[[0-9;]*m//g' <<<"${1:-}" +} + +ios_visible_len() { + local clean + clean=$(strip_ansi "${1:-}") + printf '%d' "${#clean}" +} + +pct_color() { + local n="${1:-}" + [[ "$n" =~ ^[0-9]+$ ]] || { printf '%s' "${DIM:-}"; return; } + if (( n >= 90 )); then printf '%s' "${GRAD6:-}" + elif (( n >= 75 )); then printf '%s' "${GRAD5:-}" + elif (( n >= 60 )); then printf '%s' "${GRAD4:-}" + elif (( n >= 45 )); then printf '%s' "${GRAD3:-}" + elif (( n >= 30 )); then printf '%s' "${GRAD2:-}" + elif (( n >= 15 )); then printf '%s' "${GRAD1:-}" + else printf '%s' "${GRAD0:-}" + fi +} + +ios_status_chip_label() { + local kind="${1:-idle}" + local raw pad_len pad + case "$kind" in + run|running) raw="● running" ;; + work|working|busy) raw="● working" ;; + exhaust|exhausted|capped) raw="⚠ exhaust" ;; + limit|limited|rate_limited|rate-limited) raw="◍ limited" ;; + idle|*) raw="◌ idle" ;; + esac + pad_len=$(( IOS_STATUS_CHIP_WIDTH - ${#raw} )) + (( pad_len < 0 )) && pad_len=0 + printf -v pad '%*s' "$pad_len" "" + printf '%s%s' "$raw" "$pad" +}