diff --git a/.agents/scripts/agent-test-helper.sh b/.agents/scripts/agent-test-helper.sh index a05e7f0e7..a75a349ab 100755 --- a/.agents/scripts/agent-test-helper.sh +++ b/.agents/scripts/agent-test-helper.sh @@ -50,6 +50,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit # shellcheck disable=SC2034 readonly SCRIPT_DIR +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true readonly AIDEVOPS_DIR="${HOME}/.aidevops" readonly WORKSPACE_DIR="${AIDEVOPS_DIR}/.agent-workspace" readonly TEST_DIR="${WORKSPACE_DIR}/agent-tests" @@ -99,8 +100,6 @@ log_fail() { echo -e "${RED}[FAIL]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_header() { echo -e "${PURPLE}${BOLD}$*${NC}"; } -# Cross-platform sed in-place edit (macOS vs GNU/Linux) -sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; } ####################################### # Ensure workspace directories exist diff --git a/.agents/scripts/auto-version-bump.sh b/.agents/scripts/auto-version-bump.sh index 755a596c6..a7a1c9865 100755 --- a/.agents/scripts/auto-version-bump.sh +++ b/.agents/scripts/auto-version-bump.sh @@ -19,17 +19,9 @@ print_success() { local msg="$1"; echo -e "${GREEN}[SUCCESS]${NC} $msg"; return print_warning() { local msg="$1"; echo -e "${YELLOW}[WARNING]${NC} $msg"; return 0; } print_error() { local msg="$1"; echo -e "${RED}[ERROR]${NC} $msg" >&2; return 0; } -# Cross-platform sed in-place edit (works on macOS and Linux) -sed_inplace() { - local pattern="$1" - local file="$2" - if [[ "$(uname)" == "Darwin" ]]; then - sed -i '' "$pattern" "$file" - else - sed -i "$pattern" "$file" - fi - return $? -} +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true # Repository root directory REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" || exit diff --git a/.agents/scripts/coderabbit-cli.sh b/.agents/scripts/coderabbit-cli.sh index b5066b0de..8deab28a9 100755 --- a/.agents/scripts/coderabbit-cli.sh +++ b/.agents/scripts/coderabbit-cli.sh @@ -25,6 +25,10 @@ # Version: 1.2.0 # License: MIT +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + # Colors for output readonly GREEN='\033[0;32m' readonly BLUE='\033[0;34m' @@ -131,18 +135,16 @@ apply_coderabbit_fixes() { print_info "Applying markdown formatting fixes..." # Fix heading spacing (add blank line after headings) - sed -i.tmp '/^#.*$/{ + sed_inplace '/^#.*$/{ N /\n$/!s/$/\n/ }' "$file" # Fix list spacing (ensure blank lines around lists) - sed -i.tmp '/^[[:space:]]*[-*+][[:space:]]/{ + sed_inplace '/^[[:space:]]*[-*+][[:space:]]/{ i\ }' "$file" - - rm -f "$file.tmp" print_success "Applied markdown formatting fixes" fi diff --git a/.agents/scripts/comprehensive-quality-fix.sh b/.agents/scripts/comprehensive-quality-fix.sh index 9698ef9dc..76be190e5 100755 --- a/.agents/scripts/comprehensive-quality-fix.sh +++ b/.agents/scripts/comprehensive-quality-fix.sh @@ -4,6 +4,10 @@ # Comprehensive script to fix remaining SonarCloud issues # Targets: S7679 (positional parameters), S7682 (return statements), S1192 (string literals) +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + cd providers || exit echo "🚀 Starting comprehensive quality fix..." @@ -14,7 +18,7 @@ fix_misplaced_returns() { echo "Fixing misplaced returns in $file..." # Remove return statements that are not at the end of functions - sed -i '/^ return 0$/d' "$file" + sed_inplace '/^ return 0$/d' "$file" # Add return statements to function endings that need them # This is a more targeted approach based on SonarCloud line numbers @@ -29,20 +33,20 @@ replace_string_literals() { case "$file" in "mainwp-helper.sh") # Replace remaining "Site ID is required" occurrences - sed -i 's/"Site ID is required"/"$ERROR_SITE_ID_REQUIRED"/g' "$file" - sed -i 's/"At least one site ID is required"/"$ERROR_AT_LEAST_ONE_SITE_ID"/g' "$file" + sed_inplace 's/"Site ID is required"/"$ERROR_SITE_ID_REQUIRED"/g' "$file" + sed_inplace 's/"At least one site ID is required"/"$ERROR_AT_LEAST_ONE_SITE_ID"/g' "$file" ;; "code-audit-helper.sh") # Already done in previous commit ;; "dns-helper.sh") # Replace remaining cloudflare occurrences in case statements - sed -i "s/\"namecheap\"/\"\$PROVIDER_NAMECHEAP\"/g" "$file" - sed -i "s/\"route53\"/\"\$PROVIDER_ROUTE53\"/g" "$file" + sed_inplace "s/\"namecheap\"/\"\$PROVIDER_NAMECHEAP\"/g" "$file" + sed_inplace "s/\"route53\"/\"\$PROVIDER_ROUTE53\"/g" "$file" ;; "git-platforms-helper.sh") # Replace remaining platform occurrences - sed -i "s/\"gitea\"/\"\$PLATFORM_GITEA\"/g" "$file" + sed_inplace "s/\"gitea\"/\"\$PLATFORM_GITEA\"/g" "$file" ;; *) echo "No string literal replacements needed for $file" @@ -61,22 +65,22 @@ add_missing_returns() { case "$file" in "closte-helper.sh") # Lines 134, 249 - sed -i '133a\ return 0' "$file" - sed -i '248a\ return 0' "$file" + sed_append_after 133 ' return 0' "$file" + sed_append_after 248 ' return 0' "$file" ;; "cloudron-helper.sh") # Lines 74, 202 - sed -i '73a\ return 0' "$file" - sed -i '201a\ return 0' "$file" + sed_append_after 73 ' return 0' "$file" + sed_append_after 201 ' return 0' "$file" ;; "coolify-helper.sh") # Line 236 - sed -i '235a\ return 0' "$file" + sed_append_after 235 ' return 0' "$file" ;; "dns-helper.sh") # Lines 95, 259 - sed -i '94a\ return 0' "$file" - sed -i '258a\ return 0' "$file" + sed_append_after 94 ' return 0' "$file" + sed_append_after 258 ' return 0' "$file" ;; *) diff --git a/.agents/scripts/mass-fix-returns.sh b/.agents/scripts/mass-fix-returns.sh index 3d034baa5..cb4b07224 100755 --- a/.agents/scripts/mass-fix-returns.sh +++ b/.agents/scripts/mass-fix-returns.sh @@ -4,6 +4,10 @@ # Mass fix script to add return statements to all functions that need them # Based on SonarCloud S7682 analysis +# Source shared constants (provides sed_inplace, sed_append_after) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + cd providers || exit # Files and their function ending line numbers that need return statements @@ -33,7 +37,7 @@ add_return_statement() { if ! sed -n "${prev_line}p" "$file" | grep -q "return"; then echo "Adding return statement to $file at line $line_num" # Insert return statement before the closing brace - sed -i "${prev_line}a\\ return 0" "$file" + sed_append_after "$prev_line" ' return 0' "$file" else echo "Return statement already exists in $file at line $line_num" fi diff --git a/.agents/scripts/privacy-filter-helper.sh b/.agents/scripts/privacy-filter-helper.sh index 699db6afb..b9408e9fb 100755 --- a/.agents/scripts/privacy-filter-helper.sh +++ b/.agents/scripts/privacy-filter-helper.sh @@ -30,6 +30,7 @@ readonly NC='\033[0m' # No Color # Configuration readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true readonly AIDEVOPS_DIR="${HOME}/.aidevops" readonly CONFIG_DIR="${AIDEVOPS_DIR}/config" readonly PATTERNS_FILE="${CONFIG_DIR}/privacy-patterns.txt" @@ -116,8 +117,6 @@ print_error() { return 0 } -# Cross-platform sed in-place edit (macOS vs GNU/Linux) -sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; } print_header() { local message="$1" diff --git a/.agents/scripts/quality-fix.sh b/.agents/scripts/quality-fix.sh index 5ddf0424b..6eedb31d7 100755 --- a/.agents/scripts/quality-fix.sh +++ b/.agents/scripts/quality-fix.sh @@ -5,6 +5,10 @@ set -euo pipefail +# Source shared constants if available +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + # Color codes for output readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' @@ -42,8 +46,6 @@ print_info() { return 0 } -# Cross-platform sed in-place edit (macOS vs GNU/Linux) -sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; } backup_files() { print_info "Creating backup of provider files..." diff --git a/.agents/scripts/readme-helper.sh b/.agents/scripts/readme-helper.sh index 185ebb411..d659f147d 100755 --- a/.agents/scripts/readme-helper.sh +++ b/.agents/scripts/readme-helper.sh @@ -8,6 +8,7 @@ set -euo pipefail # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" || exit AGENT_DIR="$REPO_ROOT/.agent" @@ -222,16 +223,13 @@ update_readme_counts() { # Update patterns # ~N main agents or ~N domain agents - sed -i.tmp -E "s/~[0-9]+ (main|domain) agents/~$main_agents \1 agents/g" "$readme_file" + sed_inplace -E "s/~[0-9]+ (main|domain) agents/~$main_agents \1 agents/g" "$readme_file" # N+ helper scripts - sed -i.tmp -E "s/[0-9]+\+ helper scripts/${approx_scripts}+ helper scripts/g" "$readme_file" + sed_inplace -E "s/[0-9]+\+ helper scripts/${approx_scripts}+ helper scripts/g" "$readme_file" # N+ subagent markdown files - sed -i.tmp -E "s/[0-9]+\+ subagent/${approx_subagents}+ subagent/g" "$readme_file" - - # Clean up temp files - rm -f "$readme_file.tmp" + sed_inplace -E "s/[0-9]+\+ subagent/${approx_subagents}+ subagent/g" "$readme_file" print_success "Updated README counts" print_info "Backup saved to $readme_file.bak" diff --git a/.agents/scripts/security-helper.sh b/.agents/scripts/security-helper.sh index ece544b24..0e586e463 100755 --- a/.agents/scripts/security-helper.sh +++ b/.agents/scripts/security-helper.sh @@ -10,6 +10,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit export SCRIPT_DIR readonly SCRIPT_DIR +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true readonly OUTPUT_DIR=".security-analysis" readonly VERSION="1.0.0" readonly SCAN_RESULTS_FILE=".agents/SKILL-SCAN-RESULTS.md" @@ -22,8 +23,6 @@ readonly BLUE='\033[0;34m' readonly CYAN='\033[0;36m' readonly NC='\033[0m' -# Cross-platform sed in-place edit (macOS vs GNU/Linux) -sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; } print_header() { echo -e "${CYAN}" diff --git a/.agents/scripts/shared-constants.sh b/.agents/scripts/shared-constants.sh index 149055be2..0d6875db0 100755 --- a/.agents/scripts/shared-constants.sh +++ b/.agents/scripts/shared-constants.sh @@ -244,6 +244,23 @@ sed_inplace() { return $? } +# Portable sed append-after-line (macOS vs GNU/Linux) +# BSD sed 'a' requires a backslash-newline; GNU sed accepts inline text. +# Usage: sed_append_after +sed_append_after() { + local line_num="$1" + local text="$2" + local file="$3" + if [[ "$(uname)" == "Darwin" ]]; then + sed -i '' "${line_num} a\\ +${text} +" "$file" + else + sed -i "${line_num}a\\${text}" "$file" + fi + return $? +} + # ============================================================================= # Stderr Logging Utilities # ============================================================================= diff --git a/.agents/scripts/sonarcloud-autofix.sh b/.agents/scripts/sonarcloud-autofix.sh index e63027374..1231c40c3 100755 --- a/.agents/scripts/sonarcloud-autofix.sh +++ b/.agents/scripts/sonarcloud-autofix.sh @@ -6,6 +6,10 @@ set -euo pipefail +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + # Colors for output readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' @@ -62,14 +66,12 @@ fix_positional_parameters() { cp "$file" "$file.backup" # Replace direct $1, $_arg2, etc. usage with local variable assignments - sed -i.tmp ' + sed_inplace ' s/echo "\$1"/local param1="$1"; echo "$param1"/g s/echo "\$_arg2"/local param2="$_arg2"; echo "$param2"/g s/case "\$1"/local command="$1"; case "$command"/g s/\[\[ "\$1"/local arg1="$1"; [[ "$arg1"/g ' "$file" - - rm -f "$file.tmp" print_success "Fixed positional parameters in $file" return 0 } @@ -83,7 +85,7 @@ fix_missing_default_case() { cp "$file" "$file.backup" # Add default case before esac if missing - sed -i.tmp ' + sed_inplace ' /esac/ { i\ *)\ @@ -92,8 +94,6 @@ fix_missing_default_case() { ;; } ' "$file" - - rm -f "$file.tmp" print_success "Added default cases to $file" return 0 } diff --git a/.agents/scripts/supervisor-helper.sh b/.agents/scripts/supervisor-helper.sh index 81651343e..5dc7d3345 100755 --- a/.agents/scripts/supervisor-helper.sh +++ b/.agents/scripts/supervisor-helper.sh @@ -78,6 +78,7 @@ unset _p # Configuration - resolve relative to this script's location SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit readonly SCRIPT_DIR +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true readonly SUPERVISOR_DIR="${AIDEVOPS_SUPERVISOR_DIR:-$HOME/.aidevops/.agent-workspace/supervisor}" readonly SUPERVISOR_DB="$SUPERVISOR_DIR/supervisor.db" readonly MAIL_HELPER="${SCRIPT_DIR}/mail-helper.sh" # Used by pulse command (t128.2) @@ -160,8 +161,6 @@ log_cmd() { return $rc } -# Cross-platform sed in-place edit (macOS vs GNU/Linux) -sed_inplace() { if [[ "$(uname)" == "Darwin" ]]; then sed -i '' "$@"; else sed -i "$@"; fi; } ####################################### # Get the number of CPU cores on this system @@ -4394,13 +4393,7 @@ update_todo_on_blocked() { else # Insert a new Notes line after the task local notes_line="${indent} - Notes: BLOCKED by supervisor: ${safe_reason}" - # sed append syntax differs between BSD and GNU - sed_inplace can't abstract this - if [[ "$(uname)" == "Darwin" ]]; then - sed -i '' "${line_num}a\\ -${notes_line}" "$todo_file" - else - sed -i "${line_num}a\\${notes_line}" "$todo_file" - fi + sed_append_after "$line_num" "$notes_line" "$todo_file" fi log_success "Updated TODO.md: $task_id marked blocked ($reason)" diff --git a/.agents/scripts/unstract-helper.sh b/.agents/scripts/unstract-helper.sh index 909edef1f..e609920cf 100755 --- a/.agents/scripts/unstract-helper.sh +++ b/.agents/scripts/unstract-helper.sh @@ -8,6 +8,10 @@ set -euo pipefail +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + # Constants readonly UNSTRACT_DIR="${HOME}/.aidevops/unstract" readonly UNSTRACT_REPO="https://github.com/Zipstack/unstract.git" @@ -88,7 +92,7 @@ do_install() { local frontend_env="${UNSTRACT_DIR}/frontend/.env" if [[ -f "$frontend_env" ]]; then if grep -q "REACT_APP_ENABLE_POSTHOG" "$frontend_env"; then - sed -i.bak 's/REACT_APP_ENABLE_POSTHOG=.*/REACT_APP_ENABLE_POSTHOG=false/' "$frontend_env" + sed_inplace 's/REACT_APP_ENABLE_POSTHOG=.*/REACT_APP_ENABLE_POSTHOG=false/' "$frontend_env" else echo "REACT_APP_ENABLE_POSTHOG=false" >> "$frontend_env" fi @@ -237,9 +241,8 @@ do_uninstall() { # Remove MCP env entries if [[ -f "$CREDENTIALS_FILE" ]]; then - sed -i.bak '/UNSTRACT_API_KEY/d' "$CREDENTIALS_FILE" - sed -i.bak '/^export API_BASE_URL.*unstract/d' "$CREDENTIALS_FILE" - rm -f "${CREDENTIALS_FILE}.bak" + sed_inplace '/UNSTRACT_API_KEY/d' "$CREDENTIALS_FILE" + sed_inplace '/^export API_BASE_URL.*unstract/d' "$CREDENTIALS_FILE" fi print_success "Unstract uninstalled" diff --git a/.agents/scripts/version-manager.sh b/.agents/scripts/version-manager.sh index cc4217027..bb84261d6 100755 --- a/.agents/scripts/version-manager.sh +++ b/.agents/scripts/version-manager.sh @@ -19,18 +19,9 @@ print_success() { local msg="$1"; echo -e "${GREEN}[SUCCESS]${NC} $msg"; return print_warning() { local msg="$1"; echo -e "${YELLOW}[WARNING]${NC} $msg"; return 0; } print_error() { local msg="$1"; echo -e "${RED}[ERROR]${NC} $msg" >&2; return 0; } -# Cross-platform sed in-place edit (works on macOS and Linux) -# Usage: sed_inplace 'pattern' 'file' -sed_inplace() { - local pattern="$1" - local file="$2" - if [[ "$(uname)" == "Darwin" ]]; then - sed -i '' "$pattern" "$file" - else - sed -i "$pattern" "$file" - fi - return $? -} +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true # Repository root directory # First try git (works when called from any location within a repo) diff --git a/.agents/scripts/watercrawl-helper.sh b/.agents/scripts/watercrawl-helper.sh index 007c1853e..bea38c296 100755 --- a/.agents/scripts/watercrawl-helper.sh +++ b/.agents/scripts/watercrawl-helper.sh @@ -36,6 +36,10 @@ # Version: 1.0.0 # License: MIT +# Source shared constants (provides sed_inplace and other utilities) +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" || exit +source "$SCRIPT_DIR/shared-constants.sh" 2>/dev/null || true + # Colors for output readonly GREEN='\033[0;32m' readonly BLUE='\033[0;34m' @@ -200,9 +204,8 @@ docker_setup() { api_encryption_key=$(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())" 2>/dev/null || openssl rand -base64 32) # Update .env with secure values - sed -i.bak "s|SECRET_KEY=.*|SECRET_KEY=$secret_key|" "$WATERCRAWL_DIR/docker/.env" - sed -i.bak "s|API_ENCRYPTION_KEY=.*|API_ENCRYPTION_KEY=$api_encryption_key|" "$WATERCRAWL_DIR/docker/.env" - rm -f "$WATERCRAWL_DIR/docker/.env.bak" + sed_inplace "s|SECRET_KEY=.*|SECRET_KEY=$secret_key|" "$WATERCRAWL_DIR/docker/.env" + sed_inplace "s|API_ENCRYPTION_KEY=.*|API_ENCRYPTION_KEY=$api_encryption_key|" "$WATERCRAWL_DIR/docker/.env" print_success "Environment file created with secure keys" else @@ -416,8 +419,7 @@ configure_api_key() { if [[ -f "$CREDENTIALS_FILE" ]]; then if grep -q "^export WATERCRAWL_API_KEY=" "$CREDENTIALS_FILE"; then # Update existing key - sed -i.bak "s|^export WATERCRAWL_API_KEY=.*|export WATERCRAWL_API_KEY=\"$api_key\"|" "$CREDENTIALS_FILE" - rm -f "${CREDENTIALS_FILE}.bak" + sed_inplace "s|^export WATERCRAWL_API_KEY=.*|export WATERCRAWL_API_KEY=\"$api_key\"|" "$CREDENTIALS_FILE" print_success "API key updated in $CREDENTIALS_FILE" else # Append new key @@ -463,8 +465,7 @@ configure_api_url() { if [[ -f "$CREDENTIALS_FILE" ]]; then if grep -q "^export WATERCRAWL_API_URL=" "$CREDENTIALS_FILE"; then # Update existing URL - sed -i.bak "s|^export WATERCRAWL_API_URL=.*|export WATERCRAWL_API_URL=\"$api_url\"|" "$CREDENTIALS_FILE" - rm -f "${CREDENTIALS_FILE}.bak" + sed_inplace "s|^export WATERCRAWL_API_URL=.*|export WATERCRAWL_API_URL=\"$api_url\"|" "$CREDENTIALS_FILE" print_success "API URL updated to: $api_url" else # Append new URL diff --git a/.agents/scripts/webhosting-helper.sh b/.agents/scripts/webhosting-helper.sh index 5b222caa6..76fdfa0a0 100755 --- a/.agents/scripts/webhosting-helper.sh +++ b/.agents/scripts/webhosting-helper.sh @@ -404,7 +404,11 @@ remove_domain() { # Remove from hosts file (requires manual intervention due to sudo) if grep -q "$domain" /etc/hosts; then print_warning "Please manually remove '$domain' from /etc/hosts" - print_info "Run: sudo sed -i '' '/$domain/d' /etc/hosts" + if [[ "$(uname)" == "Darwin" ]]; then + print_info "Run: sudo sed -i '' '/$domain/d' /etc/hosts" + else + print_info "Run: sudo sed -i '/$domain/d' /etc/hosts" + fi fi print_success "Domain removal complete!" diff --git a/aidevops.sh b/aidevops.sh index 893894899..ad841fdc6 100755 --- a/aidevops.sh +++ b/aidevops.sh @@ -25,6 +25,9 @@ REPOS_FILE="$CONFIG_DIR/repos.json" REPO_URL="https://github.com/marcusquinn/aidevops.git" 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; } + print_info() { echo -e "${BLUE}[INFO]${NC} $1"; } print_success() { echo -e "${GREEN}[OK]${NC} $1"; } print_warning() { echo -e "${YELLOW}[WARN]${NC} $1"; } @@ -777,8 +780,7 @@ cmd_uninstall() { # Create backup cp "$rc_file" "$rc_file.bak" # Remove our alias block (from comment to empty line) - sed -i.tmp '/# AI Assistant Server Access Framework/,/^$/d' "$rc_file" - rm -f "$rc_file.tmp" + sed_inplace '/# AI Assistant Server Access Framework/,/^$/d' "$rc_file" print_success "Removed aliases from $rc_file" fi fi @@ -1377,8 +1379,7 @@ cmd_upgrade_planning() { fi # Update date placeholder - sed -i.tmp "s/{{DATE}}/$(date +%Y-%m-%d)/" "$todo_file" 2>/dev/null || true - rm -f "${todo_file}.tmp" + sed_inplace "s/{{DATE}}/$(date +%Y-%m-%d)/" "$todo_file" 2>/dev/null || true # Merge existing tasks into Backlog section (after the TOON block closing tag) if [[ -n "$existing_tasks" ]]; then @@ -1443,8 +1444,7 @@ cmd_upgrade_planning() { fi # Update date placeholder - sed -i.tmp "s/{{DATE}}/$(date +%Y-%m-%d)/" "$plans_file" 2>/dev/null || true - rm -f "${plans_file}.tmp" + sed_inplace "s/{{DATE}}/$(date +%Y-%m-%d)/" "$plans_file" 2>/dev/null || true # Merge existing plans into Active Plans section (after the TOON block closing tag) if [[ -n "$existing_plans" ]]; then @@ -1500,8 +1500,7 @@ cmd_upgrade_planning() { ' "$config_file" > "$temp_json" && mv "$temp_json" "$config_file" else # Update existing templates_version - sed -i.tmp "s/\"templates_version\": \"[^\"]*\"/\"templates_version\": \"$aidevops_version\"/" "$config_file" 2>/dev/null || true - rm -f "${config_file}.tmp" + sed_inplace "s/\"templates_version\": \"[^\"]*\"/\"templates_version\": \"$aidevops_version\"/" "$config_file" 2>/dev/null || true fi fi