Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .agents/scripts/auto-update-helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,8 @@ check_skill_freshness() {
if [[ -n "$last_skill_check" ]]; then
local last_epoch now_epoch elapsed
if [[ "$(uname)" == "Darwin" ]]; then
last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_skill_check" "+%s" 2>/dev/null || echo "0")
# TZ=UTC: stored timestamps are UTC — macOS date -j ignores the Z suffix
last_epoch=$(TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_skill_check" "+%s" 2>/dev/null || echo "0")
else
last_epoch=$(date -d "$last_skill_check" "+%s" 2>/dev/null || echo "0")
fi
Expand Down Expand Up @@ -533,7 +534,8 @@ check_openclaw_freshness() {
if [[ -n "$last_openclaw_check" ]]; then
local last_epoch now_epoch elapsed
if [[ "$(uname)" == "Darwin" ]]; then
last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_openclaw_check" "+%s" 2>/dev/null || echo "0")
# TZ=UTC: stored timestamps are UTC — macOS date -j ignores the Z suffix
last_epoch=$(TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_openclaw_check" "+%s" 2>/dev/null || echo "0")
else
last_epoch=$(date -d "$last_openclaw_check" "+%s" 2>/dev/null || echo "0")
fi
Expand Down Expand Up @@ -744,7 +746,8 @@ check_tool_freshness() {
if [[ -n "$last_tool_check" ]]; then
local last_epoch now_epoch elapsed
if [[ "$(uname)" == "Darwin" ]]; then
last_epoch=$(date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_tool_check" "+%s" 2>/dev/null || echo "0")
# TZ=UTC: stored timestamps are UTC — macOS date -j ignores the Z suffix
last_epoch=$(TZ=UTC date -j -f "%Y-%m-%dT%H:%M:%SZ" "$last_tool_check" "+%s" 2>/dev/null || echo "0")
else
last_epoch=$(date -d "$last_tool_check" "+%s" 2>/dev/null || echo "0")
fi
Expand Down
42 changes: 33 additions & 9 deletions .agents/scripts/tool-version-check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,24 @@ get_installed_version() {

if command -v "$cmd" &>/dev/null; then
local version
# Timeout version checks — some tools (MCP servers) start a blocking
# server process when given --version instead of printing a version.
# Without a timeout, the subshell hangs forever.
# NOTE: Do NOT pipe timeout_sec to head/grep — on macOS the perl alarm
# fallback doesn't close the pipe write end on SIGALRM, causing head to
# block forever. Use a temp file instead.
local _ver_log
if ! _ver_log=$(mktemp "${TMPDIR:-/tmp}/tool-ver.XXXXXX"); then
echo "unknown"
return 0
fi
# shellcheck disable=SC2086
version=$("$cmd" $ver_flag 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "")
timeout_sec 5 "$cmd" $ver_flag >"$_ver_log" 2>/dev/null || true
version=$(head -1 "$_ver_log" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1 || echo "")
if [[ -z "$version" ]]; then
# Try alternative patterns
# shellcheck disable=SC2086
version=$("$cmd" $ver_flag 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+' | head -1 || echo "unknown")
version=$(head -1 "$_ver_log" | grep -oE '[0-9]+\.[0-9]+' | head -1 || echo "unknown")
fi
rm -f "$_ver_log"
echo "$version"
else
echo "not installed"
Expand All @@ -136,13 +147,14 @@ timeout_sec() {
# Linux has native timeout
timeout "$timeout" "$@"
else
# macOS: use perl or gtimeout if available, otherwise run without timeout
if command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$timeout" "$@"
elif command -v gtimeout &>/dev/null; then
# macOS: prefer gtimeout (robust exit codes, pipe handling) over perl alarm
if command -v gtimeout &>/dev/null; then
gtimeout "$timeout" "$@"
elif command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$timeout" "$@"
else
# No timeout available - run directly (will hang if command hangs)
echo "[WARN] No timeout command available - running without timeout" >&2
"$@"
fi
fi
Expand Down Expand Up @@ -371,11 +383,23 @@ main() {
# Run update command directly (not via eval for security)
# Commands are hardcoded in tool definitions, not user input
# Timeout prevents hangs on slow registries/network issues
if timeout 120 bash -c "$update_cmd" 2>&1 | tail -2; then
# Use timeout_sec for macOS compatibility (no native timeout)
# NOTE: Do NOT pipe timeout_sec output to tail/head — on macOS the
# perl alarm fallback doesn't close the pipe's write end on SIGALRM,
# causing tail to block forever. Use a temp file instead.
local _update_log
if ! _update_log=$(mktemp "${TMPDIR:-/tmp}/tool-update.XXXXXX"); then
echo -e " ${RED}✗ Failed to create temp log${NC}"
continue
fi
if timeout_sec 120 bash -c "$update_cmd" >"$_update_log" 2>&1; then
tail -2 "$_update_log"
echo -e " ${GREEN}✓ Updated${NC}"
else
tail -2 "$_update_log"
echo -e " ${RED}✗ Failed${NC}"
fi
rm -f "$_update_log"
echo ""
done
echo -e "${GREEN}Updates complete. Re-run to verify.${NC}"
Expand Down
20 changes: 18 additions & 2 deletions aidevops.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ VERSION_FILE="$INSTALL_DIR/VERSION"
# Portable sed in-place edit (macOS BSD sed vs GNU sed)
sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; }

# Portable timeout (macOS has no coreutils timeout)
_timeout_cmd() {
local secs="$1"
shift
if command -v timeout &>/dev/null; then
timeout "$secs" "$@"
elif command -v gtimeout &>/dev/null; then
gtimeout "$secs" "$@"
elif command -v perl &>/dev/null; then
perl -e 'alarm shift; exec @ARGV' "$secs" "$@"
else
echo "[WARN] No timeout command available - running without timeout" >&2
"$@"
fi
}

print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[OK]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; }
Expand Down Expand Up @@ -849,9 +865,9 @@ cmd_update() {
# Get latest version (npm or brew) — timeout prevents hangs on slow registries
if [[ "$pkg_ref" == brew:* ]]; then
local brew_pkg="${pkg_ref#brew:}"
latest=$(timeout 30 brew info --json=v2 "$brew_pkg" 2>/dev/null | jq -r '.formulae[0].versions.stable // empty' 2>/dev/null || true)
latest=$(_timeout_cmd 30 brew info --json=v2 "$brew_pkg" | jq -r '.formulae[0].versions.stable // empty' || true)
else
latest=$(timeout 30 npm view "$pkg_ref" version 2>/dev/null || true)
latest=$(_timeout_cmd 30 npm view "$pkg_ref" version || true)
fi
[[ -z "$latest" ]] && continue

Expand Down
Loading