aidevops 3.13.48 → 3.13.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/VERSION CHANGED
@@ -1 +1 @@
1
- 3.13.48
1
+ 3.13.50
package/aidevops.sh CHANGED
@@ -5,7 +5,7 @@
5
5
  # AI DevOps Framework CLI
6
6
  # Usage: aidevops <command> [options]
7
7
  #
8
- # Version: 3.13.48
8
+ # Version: 3.13.50
9
9
 
10
10
  set -euo pipefail
11
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.13.48",
3
+ "version": "3.13.50",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1547,6 +1547,82 @@ setup_nodejs() {
1547
1547
  return 0
1548
1548
  }
1549
1549
 
1550
+ # Bound OpenCode setup probes/installers so non-interactive setup cannot hang
1551
+ # indefinitely when an opencode shim or package manager blocks.
1552
+ _setup_opencode_timeout_cmd() {
1553
+ local timeout_seconds="$1"
1554
+ shift
1555
+
1556
+ [[ "$timeout_seconds" =~ ^[0-9]+$ ]] || timeout_seconds=5
1557
+ [[ "$timeout_seconds" -gt 0 ]] || timeout_seconds=5
1558
+
1559
+ local command_name="${1:-}"
1560
+ if [[ -n "$command_name" ]] && ! declare -F "$command_name" >/dev/null 2>&1; then
1561
+ if declare -F timeout_sec >/dev/null 2>&1; then
1562
+ timeout_sec "$timeout_seconds" "$@"
1563
+ return $?
1564
+ fi
1565
+
1566
+ if command -v gtimeout >/dev/null 2>&1; then
1567
+ gtimeout "$timeout_seconds" "$@"
1568
+ return $?
1569
+ fi
1570
+
1571
+ if command -v timeout >/dev/null 2>&1; then
1572
+ timeout "$timeout_seconds" "$@"
1573
+ return $?
1574
+ fi
1575
+ fi
1576
+
1577
+ local output_file=""
1578
+ output_file=$(mktemp "${TMPDIR:-/tmp}/aidevops-opencode-timeout.XXXXXX" 2>/dev/null || printf '')
1579
+ if [[ -z "$output_file" ]]; then
1580
+ "$@"
1581
+ return $?
1582
+ fi
1583
+
1584
+ local pid=""
1585
+ "$@" >"$output_file" 2>&1 &
1586
+ pid=$!
1587
+
1588
+ local elapsed=0
1589
+ while kill -0 "$pid" 2>/dev/null; do
1590
+ if [[ "$elapsed" -ge "$timeout_seconds" ]]; then
1591
+ kill "$pid" 2>/dev/null || true
1592
+ wait "$pid" 2>/dev/null || true
1593
+ rm -f "$output_file" 2>/dev/null || true
1594
+ return 124
1595
+ fi
1596
+ sleep 1
1597
+ elapsed=$((elapsed + 1))
1598
+ done
1599
+
1600
+ local rc=0
1601
+ wait "$pid" || rc=$?
1602
+ while IFS= read -r line; do
1603
+ printf '%s\n' "$line"
1604
+ done <"$output_file"
1605
+ rm -f "$output_file" 2>/dev/null || true
1606
+ return "$rc"
1607
+ }
1608
+
1609
+ _setup_opencode_version_output() {
1610
+ local bin="$1"
1611
+ local version_timeout="${AIDEVOPS_OPENCODE_VERSION_TIMEOUT:-5}"
1612
+
1613
+ _setup_opencode_timeout_cmd "$version_timeout" "$bin" --version
1614
+ return $?
1615
+ }
1616
+
1617
+ _setup_opencode_first_line() {
1618
+ local input="$1"
1619
+ local first_line=""
1620
+
1621
+ IFS= read -r first_line <<<"$input" || true
1622
+ printf '%s\n' "$first_line"
1623
+ return 0
1624
+ }
1625
+
1550
1626
  # t2891: Validate that an opencode binary is real anomalyco/opencode.
1551
1627
  # Mirrors the t2887 runtime canary validator (headless-runtime-lib.sh) and
1552
1628
  # the t2888 setup module validator (.agents/scripts/setup/_services.sh).
@@ -1559,7 +1635,7 @@ _setup_validate_opencode_binary() {
1559
1635
  command -v "$bin" >/dev/null 2>&1 || return 2
1560
1636
 
1561
1637
  local v
1562
- v=$("$bin" --version 2>/dev/null || echo "")
1638
+ v=$(_setup_opencode_version_output "$bin" 2>/dev/null || printf '')
1563
1639
  [[ -n "$v" ]] || return 2
1564
1640
 
1565
1641
  # Anthropic claude CLI signature — highest-confidence rejection.
@@ -1597,7 +1673,8 @@ _setup_opencode_force_heal() {
1597
1673
  return 0
1598
1674
  fi
1599
1675
 
1600
- if run_with_spinner "Reinstalling OpenCode (heal)" npm_global_install "$install_pkg"; then
1676
+ local install_timeout="${AIDEVOPS_OPENCODE_INSTALL_TIMEOUT:-180}"
1677
+ if run_with_spinner "Reinstalling OpenCode (heal)" _setup_opencode_timeout_cmd "$install_timeout" npm_global_install "$install_pkg"; then
1601
1678
  print_success "OpenCode reinstalled via $installer"
1602
1679
  else
1603
1680
  print_warning "Heal install failed via $installer"
@@ -1609,13 +1686,13 @@ _setup_opencode_force_heal() {
1609
1686
  new_bin=$(command -v opencode 2>/dev/null || echo "")
1610
1687
  if [[ -n "$new_bin" ]] && _setup_validate_opencode_binary "$new_bin"; then
1611
1688
  local new_v
1612
- new_v=$("$new_bin" --version 2>/dev/null | head -1 || echo "unknown")
1689
+ new_v=$(_setup_opencode_first_line "$(_setup_opencode_version_output "$new_bin" 2>/dev/null || printf 'unknown')")
1613
1690
  print_success "OpenCode CLI: $new_bin ($new_v)"
1614
1691
  mkdir -p "${HOME}/.aidevops" 2>/dev/null || true
1615
1692
  printf '%s\n' "$new_bin" >"${HOME}/.aidevops/.opencode-bin-resolved" 2>/dev/null || true
1616
1693
  else
1617
1694
  local v_after
1618
- v_after=$("$new_bin" --version 2>/dev/null | head -1 || echo "<missing>")
1695
+ v_after=$(_setup_opencode_first_line "$(_setup_opencode_version_output "$new_bin" 2>/dev/null || printf '<missing>')")
1619
1696
  print_warning "Post-heal validation still failing: '$new_bin' returns '$v_after'"
1620
1697
  print_info "Check PATH: 'which -a opencode' — npm/bun global bin dir must come first"
1621
1698
  fi
@@ -1648,7 +1725,7 @@ setup_opencode_cli() {
1648
1725
  # Already valid → record + early return.
1649
1726
  if [[ $validate_rc -eq 0 ]]; then
1650
1727
  local oc_version
1651
- oc_version=$("$current_bin" --version 2>/dev/null | head -1 || echo "unknown")
1728
+ oc_version=$(_setup_opencode_first_line "$(_setup_opencode_version_output "$current_bin" 2>/dev/null || printf 'unknown')")
1652
1729
  print_success "OpenCode already installed: $oc_version"
1653
1730
  mkdir -p "${HOME}/.aidevops" 2>/dev/null || true
1654
1731
  printf '%s\n' "$current_bin" >"${HOME}/.aidevops/.opencode-bin-resolved" 2>/dev/null || true
@@ -1658,7 +1735,7 @@ setup_opencode_cli() {
1658
1735
  # Wrong package → auto-heal (no prompt).
1659
1736
  if [[ $validate_rc -eq 1 ]]; then
1660
1737
  local wrong_v
1661
- wrong_v=$("$current_bin" --version 2>/dev/null | head -1 || echo "<unknown>")
1738
+ wrong_v=$(_setup_opencode_first_line "$(_setup_opencode_version_output "$current_bin" 2>/dev/null || printf '<unknown>')")
1662
1739
  _setup_opencode_force_heal "$install_pkg" "$current_bin" "$wrong_v"
1663
1740
  return 0
1664
1741
  fi
@@ -1682,7 +1759,8 @@ setup_opencode_cli() {
1682
1759
  local install_oc
1683
1760
  setup_prompt install_oc "Install OpenCode via $installer? [Y/n]: " "Y"
1684
1761
  if [[ "$install_oc" =~ ^[Yy]?$ ]]; then
1685
- if run_with_spinner "Installing OpenCode" npm_global_install "$install_pkg"; then
1762
+ local install_timeout="${AIDEVOPS_OPENCODE_INSTALL_TIMEOUT:-180}"
1763
+ if run_with_spinner "Installing OpenCode" _setup_opencode_timeout_cmd "$install_timeout" npm_global_install "$install_pkg"; then
1686
1764
  print_success "OpenCode installed"
1687
1765
 
1688
1766
  # Persist resolved path on first-time success too (t2891).
package/setup.sh CHANGED
@@ -12,7 +12,7 @@ shopt -s inherit_errexit 2>/dev/null || true
12
12
  # AI Assistant Server Access Framework Setup Script
13
13
  # Helps developers set up the framework for their infrastructure
14
14
  #
15
- # Version: 3.13.48
15
+ # Version: 3.13.50
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)
@@ -143,34 +143,40 @@ _cron_escape() {
143
143
  }
144
144
 
145
145
  # GH#21060 / t2911: Per-stage timing helper for non-interactive setup runs.
146
- # Wraps a function call, records start/end time, and appends one TSV line to
146
+ # Wraps a function call, records start/end time, and appends TSV lines to
147
147
  # $HOME/.aidevops/logs/setup-stage-timings.log:
148
148
  # iso8601_utc <TAB> stage_name <TAB> duration_seconds <TAB> exit_code
149
+ # A RUNNING row is written before each stage starts so a tool/worker timeout
150
+ # still leaves the currently executing phase in the timing log.
149
151
  # Usage: _time_step "stage_name" function_name [args...]
150
152
  # ShellCheck: $@ is used deliberately (SC2068 not applicable; no word-splitting
151
153
  # issue since we shift the stage-name arg first and pass the rest as a command).
154
+ _time_step_log() {
155
+ local _ts_stage="$1"
156
+ local _ts_duration="$2"
157
+ local _ts_exit="$3"
158
+ printf '%s\t%s\t%s\t%s\n' \
159
+ "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
160
+ "$_ts_stage" \
161
+ "$_ts_duration" \
162
+ "$_ts_exit" \
163
+ >>"$HOME/.aidevops/logs/setup-stage-timings.log" 2>/dev/null || true
164
+ return 0
165
+ }
166
+
152
167
  _time_step() {
153
168
  local _ts_stage="$1"
154
169
  shift
155
- # GH#22012: In non-interactive mode, emit the stage name before running so
156
- # an operator watching setup.sh output can identify which step is blocking.
157
- # The TSV log entry below is written AFTER the step returns — it provides no
158
- # signal during a hang. This print is the only in-flight indicator.
159
- if [[ "${NON_INTERACTIVE:-false}" == "true" ]]; then
160
- printf '[SETUP] stage: %s\n' "$_ts_stage"
161
- fi
162
170
  local _ts_start _ts_end _ts_duration _ts_exit
171
+ print_info "Starting setup stage: $_ts_stage"
172
+ _time_step_log "$_ts_stage" "0.00" "RUNNING"
163
173
  _ts_start=$(date +%s.%N 2>/dev/null || date +%s)
164
174
  _ts_exit=0
165
175
  "$@" || _ts_exit=$?
166
176
  _ts_end=$(date +%s.%N 2>/dev/null || date +%s)
167
177
  _ts_duration=$(awk -v a="$_ts_start" -v b="$_ts_end" 'BEGIN { printf "%.2f", b - a }')
168
- printf '%s\t%s\t%s\t%s\n' \
169
- "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
170
- "$_ts_stage" \
171
- "$_ts_duration" \
172
- "$_ts_exit" \
173
- >>"$HOME/.aidevops/logs/setup-stage-timings.log" 2>/dev/null || true
178
+ _time_step_log "$_ts_stage" "$_ts_duration" "$_ts_exit"
179
+ print_info "Finished setup stage: $_ts_stage (${_ts_duration}s, exit=${_ts_exit})"
174
180
  return "$_ts_exit"
175
181
  }
176
182