aidevops 3.11.9 → 3.11.11

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.11.9
1
+ 3.11.11
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.11.9
8
+ # Version: 3.11.11
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.11.9",
3
+ "version": "3.11.11",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1514,24 +1514,124 @@ setup_nodejs() {
1514
1514
  return 0
1515
1515
  }
1516
1516
 
1517
- setup_opencode_cli() {
1518
- print_info "Setting up OpenCode CLI..."
1517
+ # t2891: Validate that an opencode binary is real anomalyco/opencode.
1518
+ # Mirrors the t2887 runtime canary validator (headless-runtime-lib.sh) and
1519
+ # the t2888 setup module validator (.agents/scripts/setup/_services.sh).
1520
+ # Inlined to keep tool-install.sh self-contained — sourced from setup.sh
1521
+ # during early bootstrap before headless-runtime-lib.sh is on the path.
1522
+ # Returns: 0=valid, 1=wrong package (e.g. claude CLI), 2=missing/unrunnable.
1523
+ _setup_validate_opencode_binary() {
1524
+ local bin="${1:-}"
1525
+ [[ -n "$bin" ]] || return 2
1526
+ command -v "$bin" >/dev/null 2>&1 || return 2
1527
+
1528
+ local v
1529
+ v=$("$bin" --version 2>/dev/null || echo "")
1530
+ [[ -n "$v" ]] || return 2
1531
+
1532
+ # Anthropic claude CLI signature — highest-confidence rejection.
1533
+ [[ "$v" == *"(Claude Code)"* ]] && return 1
1534
+
1535
+ # opencode is at 1.x; any 2.x+ is wrong (claude CLI is 2.1.x).
1536
+ [[ "$v" =~ ^[2-9][0-9]*\. ]] && return 1
1537
+
1538
+ # Sanity: must look like a semver (X.Y.Z).
1539
+ [[ "$v" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]] || return 1
1519
1540
 
1520
- # Check if OpenCode is already installed
1521
- if command -v opencode >/dev/null 2>&1; then
1522
- local oc_version
1523
- oc_version=$(opencode --version 2>/dev/null | head -1 || echo "unknown")
1524
- print_success "OpenCode already installed: $oc_version"
1541
+ return 0
1542
+ }
1543
+
1544
+ # t2891: detect-and-heal when 'opencode' bin name is owned by a wrong
1545
+ # package (canonical case: @anthropic-ai/claude-code shadowing
1546
+ # anomalyco/opencode after a npm install collision). Auto-installs
1547
+ # without prompt because:
1548
+ # 1) it's healing a broken state, not first-time setup
1549
+ # 2) non-interactive runners (the canonical victim) would auto-Y anyway
1550
+ # Idempotent. Fail-open if no installer available.
1551
+ _setup_opencode_force_heal() {
1552
+ local install_pkg="$1" wrong_bin="$2" wrong_v="$3"
1553
+ print_warning "OpenCode binary at '$wrong_bin' is the wrong package ('$wrong_v')"
1554
+ print_info "Forcing reinstall of $install_pkg to heal bin collision (t2891)..."
1555
+
1556
+ local installer=""
1557
+ if command -v bun >/dev/null 2>&1; then
1558
+ installer="bun"
1559
+ elif command -v npm >/dev/null 2>&1; then
1560
+ installer="npm"
1561
+ else
1562
+ print_warning "Neither bun nor npm found — cannot heal OpenCode binary"
1563
+ print_info "Install Node.js or Bun first, then re-run 'aidevops update'"
1525
1564
  return 0
1526
1565
  fi
1527
1566
 
1528
- # Need either bun or npm to install
1529
- local installer=""
1567
+ if run_with_spinner "Reinstalling OpenCode (heal)" npm_global_install "$install_pkg"; then
1568
+ print_success "OpenCode reinstalled via $installer"
1569
+ else
1570
+ print_warning "Heal install failed via $installer"
1571
+ print_info "Try manually: $installer install -g $install_pkg"
1572
+ fi
1573
+
1574
+ # Re-validate post-heal.
1575
+ local new_bin
1576
+ new_bin=$(command -v opencode 2>/dev/null || echo "")
1577
+ if [[ -n "$new_bin" ]] && _setup_validate_opencode_binary "$new_bin"; then
1578
+ local new_v
1579
+ new_v=$("$new_bin" --version 2>/dev/null | head -1 || echo "unknown")
1580
+ print_success "OpenCode CLI: $new_bin ($new_v)"
1581
+ mkdir -p "${HOME}/.aidevops" 2>/dev/null || true
1582
+ printf '%s\n' "$new_bin" >"${HOME}/.aidevops/.opencode-bin-resolved" 2>/dev/null || true
1583
+ else
1584
+ local v_after
1585
+ v_after=$("$new_bin" --version 2>/dev/null | head -1 || echo "<missing>")
1586
+ print_warning "Post-heal validation still failing: '$new_bin' returns '$v_after'"
1587
+ print_info "Check PATH: 'which -a opencode' — npm/bun global bin dir must come first"
1588
+ fi
1589
+ return 0
1590
+ }
1591
+
1592
+ setup_opencode_cli() {
1593
+ print_info "Setting up OpenCode CLI..."
1594
+
1530
1595
  # Respect OPENCODE_PINNED_VERSION from shared-constants.sh if sourced,
1531
1596
  # otherwise fall back to latest.
1532
1597
  local pin_ver="${OPENCODE_PINNED_VERSION:-latest}"
1533
1598
  local install_pkg="opencode-ai@${pin_ver}"
1534
1599
 
1600
+ # t2891: validate the resolved binary is anomalyco/opencode, not a
1601
+ # wrong package (claude CLI etc) that took the 'opencode' bin name.
1602
+ # Without this, alex-solovyev's runner — where command -v opencode
1603
+ # resolves to @anthropic-ai/claude-code — silently passes through
1604
+ # this function, leaving t2887's runtime canary to throttle the spam
1605
+ # without ever healing the binary.
1606
+ local current_bin
1607
+ current_bin=$(command -v opencode 2>/dev/null || echo "")
1608
+ local validate_rc=0
1609
+ if [[ -n "$current_bin" ]]; then
1610
+ _setup_validate_opencode_binary "$current_bin" || validate_rc=$?
1611
+ else
1612
+ validate_rc=2
1613
+ fi
1614
+
1615
+ # Already valid → record + early return.
1616
+ if [[ $validate_rc -eq 0 ]]; then
1617
+ local oc_version
1618
+ oc_version=$("$current_bin" --version 2>/dev/null | head -1 || echo "unknown")
1619
+ print_success "OpenCode already installed: $oc_version"
1620
+ mkdir -p "${HOME}/.aidevops" 2>/dev/null || true
1621
+ printf '%s\n' "$current_bin" >"${HOME}/.aidevops/.opencode-bin-resolved" 2>/dev/null || true
1622
+ return 0
1623
+ fi
1624
+
1625
+ # Wrong package → auto-heal (no prompt).
1626
+ if [[ $validate_rc -eq 1 ]]; then
1627
+ local wrong_v
1628
+ wrong_v=$("$current_bin" --version 2>/dev/null | head -1 || echo "<unknown>")
1629
+ _setup_opencode_force_heal "$install_pkg" "$current_bin" "$wrong_v"
1630
+ return 0
1631
+ fi
1632
+
1633
+ # Missing → first-time install path (preserves prompt for interactive UX).
1634
+ local installer=""
1535
1635
  if command -v bun >/dev/null 2>&1; then
1536
1636
  installer="bun"
1537
1637
  elif command -v npm >/dev/null 2>&1; then
@@ -1552,6 +1652,14 @@ setup_opencode_cli() {
1552
1652
  if run_with_spinner "Installing OpenCode" npm_global_install "$install_pkg"; then
1553
1653
  print_success "OpenCode installed"
1554
1654
 
1655
+ # Persist resolved path on first-time success too (t2891).
1656
+ local new_bin
1657
+ new_bin=$(command -v opencode 2>/dev/null || echo "")
1658
+ if [[ -n "$new_bin" ]] && _setup_validate_opencode_binary "$new_bin"; then
1659
+ mkdir -p "${HOME}/.aidevops" 2>/dev/null || true
1660
+ printf '%s\n' "$new_bin" >"${HOME}/.aidevops/.opencode-bin-resolved" 2>/dev/null || true
1661
+ fi
1662
+
1555
1663
  # Offer authentication
1556
1664
  echo ""
1557
1665
  print_info "OpenCode needs authentication to use AI models."
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.11.9
15
+ # Version: 3.11.11
16
16
  #
17
17
  # Quick Install:
18
18
  # npm install -g aidevops && aidevops update (recommended)