aidevops 3.5.179 → 3.5.181

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.5.179
1
+ 3.5.181
package/aidevops.sh CHANGED
@@ -3,7 +3,7 @@
3
3
  # AI DevOps Framework CLI
4
4
  # Usage: aidevops <command> [options]
5
5
  #
6
- # Version: 3.5.179
6
+ # Version: 3.5.181
7
7
 
8
8
  set -euo pipefail
9
9
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aidevops",
3
- "version": "3.5.179",
3
+ "version": "3.5.181",
4
4
  "description": "AI DevOps Framework - AI-assisted development workflows, code quality, and deployment automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -685,7 +685,7 @@ setup_beads() {
685
685
  # _install_bv_tool: install the bv (beads_viewer) TUI tool.
686
686
  # Returns 0 if installed, 1 if skipped or failed.
687
687
  _install_bv_tool() {
688
- read -r -p " Install bv (TUI with PageRank, critical path, graph analytics)? [Y/n]: " install_viewer
688
+ setup_prompt install_viewer " Install bv (TUI with PageRank, critical path, graph analytics)? [Y/n]: " "Y"
689
689
  if [[ ! "$install_viewer" =~ ^[Yy]?$ ]]; then
690
690
  print_info "Install later:"
691
691
  print_info " Homebrew: brew tap dicklesworthstone/tap && brew install dicklesworthstone/tap/bv"
@@ -711,7 +711,7 @@ _install_bv_tool() {
711
711
  fi
712
712
  else
713
713
  # Offer verified install script (download-then-execute, not piped)
714
- read -r -p " Install bv via install script? [Y/n]: " use_script
714
+ setup_prompt use_script " Install bv via install script? [Y/n]: " "Y"
715
715
  if [[ "$use_script" =~ ^[Yy]?$ ]]; then
716
716
  if verified_install "bv (beads viewer)" "https://raw.githubusercontent.com/Dicklesworthstone/beads_viewer/main/install.sh"; then
717
717
  print_info "Run: bv (in a beads-enabled project)"
@@ -738,14 +738,14 @@ _install_beads_node_tools() {
738
738
  echo "$count"
739
739
  return 0
740
740
  fi
741
- read -r -p " Install beads-ui (Web dashboard)? [Y/n]: " install_web
741
+ setup_prompt install_web " Install beads-ui (Web dashboard)? [Y/n]: " "Y"
742
742
  if [[ "$install_web" =~ ^[Yy]?$ ]]; then
743
743
  if run_with_spinner "Installing beads-ui" npm_global_install beads-ui; then
744
744
  print_info "Run: beads-ui"
745
745
  count=$((count + 1))
746
746
  fi
747
747
  fi
748
- read -r -p " Install bdui (React/Ink TUI)? [Y/n]: " install_bdui
748
+ setup_prompt install_bdui " Install bdui (React/Ink TUI)? [Y/n]: " "Y"
749
749
  if [[ "$install_bdui" =~ ^[Yy]?$ ]]; then
750
750
  if run_with_spinner "Installing bdui" npm_global_install bdui; then
751
751
  print_info "Run: bdui"
@@ -762,7 +762,7 @@ _install_perles() {
762
762
  if ! command -v cargo &>/dev/null; then
763
763
  return 1
764
764
  fi
765
- read -r -p " Install perles (BQL query language TUI)? [Y/n]: " install_perles
765
+ setup_prompt install_perles " Install perles (BQL query language TUI)? [Y/n]: " "Y"
766
766
  if [[ ! "$install_perles" =~ ^[Yy]?$ ]]; then
767
767
  return 1
768
768
  fi
@@ -782,7 +782,7 @@ setup_beads_ui() {
782
782
  echo " • perles (Rust) - BQL query language TUI"
783
783
  echo ""
784
784
 
785
- read -r -p "Install optional Beads UI tools? [Y/n]: " install_beads_ui
785
+ setup_prompt install_beads_ui "Install optional Beads UI tools? [Y/n]: " "Y"
786
786
 
787
787
  if [[ ! "$install_beads_ui" =~ ^[Yy]?$ ]]; then
788
788
  print_info "Skipped Beads UI tools (can install later from beads.md docs)"
@@ -151,14 +151,29 @@ bootstrap_repo() {
151
151
  print_info "Remote install detected - bootstrapping repository..."
152
152
 
153
153
  # On macOS, offer choice: install locally or in an OrbStack VM
154
- if [[ "$(uname)" == "Darwin" ]]; then
154
+ # Skip prompt in non-interactive mode (parse_args hasn't run yet,
155
+ # so check $@ directly for --non-interactive/-n flags)
156
+ local _bootstrap_non_interactive=false
157
+ local _arg
158
+ for _arg in "$@"; do
159
+ case "$_arg" in
160
+ --non-interactive | -n) _bootstrap_non_interactive=true ;;
161
+ esac
162
+ done
163
+ [[ "${AIDEVOPS_NON_INTERACTIVE:-false}" == "true" ]] && _bootstrap_non_interactive=true
164
+ [[ ! -t 0 ]] && _bootstrap_non_interactive=true
165
+
166
+ if [[ "$(uname)" == "Darwin" && "$_bootstrap_non_interactive" == "false" ]]; then
155
167
  echo ""
156
168
  echo "Where would you like to install aidevops?"
157
169
  echo ""
158
170
  echo " 1) Install on this Mac (recommended)"
159
171
  echo " 2) Install in a Linux VM (via OrbStack)"
160
172
  echo ""
161
- read -r -p "Choose [1/2] (default: 1): " install_target
173
+ # Cannot use setup_prompt here — _common.sh not yet sourced during bootstrap.
174
+ # The _bootstrap_non_interactive guard above prevents reaching this line.
175
+ local install_target=""
176
+ read -r -p "Choose [1/2] (default: 1): " install_target || install_target="1"
162
177
 
163
178
  if [[ "$install_target" == "2" ]]; then
164
179
  print_info "Setting up OrbStack VM installation..."
@@ -301,7 +316,7 @@ ensure_homebrew() {
301
316
  print_info "Homebrew (Linuxbrew) is not installed."
302
317
  print_info "Several optional tools (Beads CLI, Worktrunk, bv) install via Homebrew taps."
303
318
  echo ""
304
- read -r -p "Install Homebrew for Linux? [Y/n]: " install_brew
319
+ setup_prompt install_brew "Install Homebrew for Linux? [Y/n]: " "Y"
305
320
 
306
321
  if [[ ! "$install_brew" =~ ^[Yy]?$ ]]; then
307
322
  print_info "Skipped Homebrew installation"
@@ -497,7 +512,7 @@ check_requirements() {
497
512
  fi
498
513
 
499
514
  echo ""
500
- read -r -p "Install missing dependencies using $pkg_manager? [Y/n]: " install_deps
515
+ setup_prompt install_deps "Install missing dependencies using $pkg_manager? [Y/n]: " "Y"
501
516
 
502
517
  if [[ "$install_deps" =~ ^[Yy]?$ ]]; then
503
518
  print_info "Installing ${missing_packages[*]}..."
@@ -567,7 +582,7 @@ check_quality_tools() {
567
582
  fi
568
583
 
569
584
  echo ""
570
- read -r -p "Install quality tools using $pkg_manager? [Y/n]: " install_quality
585
+ setup_prompt install_quality "Install quality tools using $pkg_manager? [Y/n]: " "Y"
571
586
 
572
587
  if [[ "$install_quality" =~ ^[Yy]?$ ]]; then
573
588
  print_info "Installing ${missing_tools[*]}..."
@@ -261,7 +261,7 @@ setup_localwp_mcp() {
261
261
  fi
262
262
 
263
263
  print_info "LocalWP MCP server enables AI assistants to query WordPress databases"
264
- read -r -p "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? [Y/n]: " install_mcp
264
+ setup_prompt install_mcp "Install LocalWP MCP server (@verygoodplugins/mcp-local-wp)? [Y/n]: " "Y"
265
265
 
266
266
  if [[ "$install_mcp" =~ ^[Yy]?$ ]]; then
267
267
  if run_with_spinner "Installing LocalWP MCP server" npm_global_install "@verygoodplugins/mcp-local-wp"; then
@@ -402,7 +402,7 @@ _setup_browser_tools_playwright() {
402
402
  fi
403
403
 
404
404
  local install_playwright
405
- read -r -p "Install Playwright MCP with browsers (chromium, firefox, webkit)? [Y/n]: " install_playwright
405
+ setup_prompt install_playwright "Install Playwright MCP with browsers (chromium, firefox, webkit)? [Y/n]: " "Y"
406
406
 
407
407
  if [[ "$install_playwright" =~ ^[Yy]?$ ]]; then
408
408
  print_info "Installing Playwright browsers..."
@@ -875,7 +875,7 @@ _setup_quickfile_mcp_clone_and_build() {
875
875
 
876
876
  print_info "QuickFile MCP provides AI access to UK accounting (invoices, clients, reports)"
877
877
  local install_qf
878
- read -r -p "Clone and build QuickFile MCP server? [Y/n]: " install_qf
878
+ setup_prompt install_qf "Clone and build QuickFile MCP server? [Y/n]: " "Y"
879
879
 
880
880
  if [[ ! "$install_qf" =~ ^[Yy]?$ ]]; then
881
881
  print_info "Skipped QuickFile MCP installation"
@@ -614,7 +614,7 @@ setup_multi_tenant_credentials() {
614
614
  print_info "Everything continues to work as before - this is non-breaking."
615
615
  echo ""
616
616
 
617
- read -r -p "Enable multi-tenant credential storage? [Y/n]: " enable_mt
617
+ setup_prompt enable_mt "Enable multi-tenant credential storage? [Y/n]: " "Y"
618
618
  enable_mt=$(echo "$enable_mt" | tr '[:upper:]' '[:lower:]')
619
619
 
620
620
  if [[ "$enable_mt" =~ ^[Yy]?$ || "$enable_mt" == "yes" ]]; then
@@ -681,7 +681,7 @@ check_tool_updates() {
681
681
  bash "$tool_check_script" --quiet
682
682
  echo ""
683
683
 
684
- read -r -p "Update all outdated tools now? [Y/n]: " do_update
684
+ setup_prompt do_update "Update all outdated tools now? [Y/n]: " "Y"
685
685
 
686
686
  if [[ "$do_update" =~ ^[Yy]?$ || "$do_update" == "Y" ]]; then
687
687
  print_info "Updating tools..."
@@ -39,7 +39,7 @@ setup_auto_update() {
39
39
  echo "Auto-update keeps aidevops current by checking every 10 minutes."
40
40
  echo "Safe to run while AI sessions are active."
41
41
  echo ""
42
- read -r -p "Enable auto-update? [Y/n]: " enable_auto
42
+ setup_prompt enable_auto "Enable auto-update? [Y/n]: " "Y"
43
43
  if [[ "$enable_auto" =~ ^[Yy]?$ ]]; then
44
44
  bash "$auto_update_script" enable
45
45
  else
@@ -179,7 +179,7 @@ setup_tabby() {
179
179
  echo ""
180
180
  bash "$tabby_helper" status || true
181
181
  echo ""
182
- read -r -p "Sync Tabby profiles from repos.json? [Y/n]: " sync_tabby
182
+ setup_prompt sync_tabby "Sync Tabby profiles from repos.json? [Y/n]: " "Y"
183
183
  if [[ "$sync_tabby" =~ ^[Yy]?$ ]]; then
184
184
  bash "$tabby_helper" sync
185
185
  else
@@ -227,7 +227,7 @@ setup_onboarding_prompt() {
227
227
  echo " - Get personalized recommendations based on your work"
228
228
  echo " - Set up API keys and credentials interactively"
229
229
  echo ""
230
- read -r -p "Launch ${_onb_name} with /onboarding now? [Y/n]: " launch_onboarding
230
+ setup_prompt launch_onboarding "Launch ${_onb_name} with /onboarding now? [Y/n]: " "Y"
231
231
  if [[ "$launch_onboarding" =~ ^[Yy]?$ ]]; then
232
232
  echo ""
233
233
  echo "Starting ${_onb_name} with onboarding wizard..."
@@ -76,7 +76,7 @@ _determine_pulse_install() {
76
76
  echo " - 4-hourly strategic review (opus-tier) for queue health" >&2
77
77
  echo " - Circuit breaker pauses dispatch on consecutive failures" >&2
78
78
  echo "" >&2
79
- read -r -p "Enable supervisor pulse? [y/N]: " enable_pulse
79
+ setup_prompt enable_pulse "Enable supervisor pulse? [y/N]: " "n"
80
80
  if [[ "$enable_pulse" =~ ^[Yy]$ ]]; then
81
81
  _do_install=true
82
82
  # Record explicit consent
@@ -1263,7 +1263,7 @@ setup_repo_sync() {
1263
1263
  echo "Repo sync keeps your local git repos up to date by running"
1264
1264
  echo "git pull --ff-only daily on clean repos on their default branch."
1265
1265
  echo ""
1266
- read -r -p "Enable daily repo sync? [Y/n]: " enable_repo_sync
1266
+ setup_prompt enable_repo_sync "Enable daily repo sync? [Y/n]: " "Y"
1267
1267
  if [[ "$enable_repo_sync" =~ ^[Yy]?$ || -z "$enable_repo_sync" ]]; then
1268
1268
  bash "$repo_sync_script" enable
1269
1269
  else
@@ -101,7 +101,7 @@ _omz_offer_shell_change() {
101
101
  fi
102
102
 
103
103
  echo ""
104
- read -r -p "Change default shell to zsh? [y/N]: " change_shell
104
+ setup_prompt change_shell "Change default shell to zsh? [y/N]: " "n"
105
105
  if [[ "$change_shell" =~ ^[Yy]$ ]]; then
106
106
  if chsh -s "$(command -v zsh)"; then
107
107
  print_success "Default shell changed to zsh"
@@ -165,7 +165,7 @@ setup_oh_my_zsh() {
165
165
  echo " This is optional - plain zsh works fine without it."
166
166
  echo ""
167
167
 
168
- read -r -p "Install Oh My Zsh? [y/N]: " install_omz
168
+ setup_prompt install_omz "Install Oh My Zsh? [y/N]: " "n"
169
169
 
170
170
  if [[ "$install_omz" =~ ^[Yy]$ ]]; then
171
171
  _omz_run_install "$default_shell"
@@ -435,10 +435,8 @@ _shell_compat_prompt_user() {
435
435
  print_info "both bash and zsh, so your customizations work in either shell."
436
436
  echo ""
437
437
 
438
- local setup_compat="Y"
439
- if [[ "$NON_INTERACTIVE" != "true" ]]; then
440
- read -r -p "Create shared shell profile for cross-shell compatibility? [Y/n]: " setup_compat
441
- fi
438
+ local setup_compat
439
+ setup_prompt setup_compat "Create shared shell profile for cross-shell compatibility? [Y/n]: " "Y"
442
440
 
443
441
  if [[ ! "$setup_compat" =~ ^[Yy]?$ ]]; then
444
442
  print_info "Skipped cross-shell compatibility setup"
@@ -538,7 +536,7 @@ check_optional_deps() {
538
536
  pkg_manager=$(detect_package_manager)
539
537
 
540
538
  if [[ "$pkg_manager" != "unknown" ]]; then
541
- read -r -p "Install optional dependencies using $pkg_manager? [Y/n]: " install_optional
539
+ setup_prompt install_optional "Install optional dependencies using $pkg_manager? [Y/n]: " "Y"
542
540
 
543
541
  if [[ "$install_optional" =~ ^[Yy]?$ ]]; then
544
542
  print_info "Installing ${missing_optional[*]}..."
@@ -1097,7 +1095,7 @@ setup_aliases() {
1097
1095
  fi
1098
1096
 
1099
1097
  print_info "Detected default shell: $default_shell"
1100
- read -r -p "Add shell aliases? [Y/n]: " add_aliases
1098
+ setup_prompt add_aliases "Add shell aliases? [Y/n]: " "Y"
1101
1099
 
1102
1100
  if [[ "$add_aliases" =~ ^[Yy]?$ ]]; then
1103
1101
  local added_to
@@ -1162,7 +1160,7 @@ _terminal_title_prompt_and_install() {
1162
1160
  local setup_script="$1"
1163
1161
 
1164
1162
  echo ""
1165
- read -r -p "Install terminal title integration? [Y/n]: " install_title
1163
+ setup_prompt install_title "Install terminal title integration? [Y/n]: " "Y"
1166
1164
 
1167
1165
  if [[ "$install_title" =~ ^[Yy]?$ ]]; then
1168
1166
  if bash "$setup_script" install; then
@@ -47,7 +47,7 @@ setup_git_clis() {
47
47
 
48
48
  if [[ "$pkg_manager" != "unknown" ]]; then
49
49
  echo ""
50
- read -r -p "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " install_git_clis
50
+ setup_prompt install_git_clis "Install Git CLI tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " "Y"
51
51
 
52
52
  if [[ "$install_git_clis" =~ ^[Yy]?$ ]]; then
53
53
  print_info "Installing ${missing_packages[*]}..."
@@ -229,10 +229,7 @@ setup_file_discovery_tools() {
229
229
  pkg_manager=$(detect_package_manager)
230
230
 
231
231
  if [[ "$pkg_manager" != "unknown" ]]; then
232
- local install_fd_tools="y"
233
- if [[ "$INTERACTIVE_MODE" == "true" ]]; then
234
- read -r -p "Install file discovery tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " install_fd_tools
235
- fi
232
+ setup_prompt install_fd_tools "Install file discovery tools (${missing_packages[*]}) using $pkg_manager? [Y/n]: " "Y"
236
233
 
237
234
  if [[ "$install_fd_tools" =~ ^[Yy]?$ ]]; then
238
235
  _install_file_discovery_packages "$pkg_manager" "${missing_packages[@]}"
@@ -271,10 +268,7 @@ setup_rtk() {
271
268
  echo " Single binary, zero dependencies, <10ms overhead."
272
269
  echo ""
273
270
 
274
- local install_rtk="n"
275
- if [[ "$INTERACTIVE_MODE" == "true" ]]; then
276
- read -r -p "Install rtk for token-optimized CLI output? [y/N]: " install_rtk
277
- fi
271
+ setup_prompt install_rtk "Install rtk for token-optimized CLI output? [y/N]: " "n"
278
272
 
279
273
  if [[ "$install_rtk" =~ ^[Yy]$ ]]; then
280
274
  VERIFIED_INSTALL_SHELL="sh"
@@ -371,11 +365,7 @@ setup_shell_linting_tools() {
371
365
 
372
366
  if [[ "$pkg_manager" != "unknown" ]]; then
373
367
  local install_linters
374
- if [[ "${NON_INTERACTIVE:-}" == "true" ]]; then
375
- install_linters="Y"
376
- else
377
- read -r -p "Install missing shell linting tools using $pkg_manager? [Y/n]: " install_linters
378
- fi
368
+ setup_prompt install_linters "Install missing shell linting tools using $pkg_manager? [Y/n]: " "Y"
379
369
 
380
370
  if [[ "$install_linters" =~ ^[Yy]?$ ]]; then
381
371
  if install_packages "$pkg_manager" "${missing_tools[@]}"; then
@@ -508,10 +498,8 @@ setup_qlty_cli() {
508
498
  echo " - Used by the daily code quality sweep (pulse-wrapper.sh)"
509
499
  echo ""
510
500
 
511
- local install_qlty="Y"
512
- if [[ "${NON_INTERACTIVE:-}" != "true" ]]; then
513
- read -r -p "Install Qlty CLI? [Y/n]: " install_qlty
514
- fi
501
+ local install_qlty
502
+ setup_prompt install_qlty "Install Qlty CLI? [Y/n]: " "Y"
515
503
 
516
504
  if [[ "$install_qlty" =~ ^[Yy]?$ ]]; then
517
505
  if command -v curl >/dev/null 2>&1; then
@@ -612,7 +600,7 @@ _check_worktrunk_shell_integration() {
612
600
  if [[ "$wt_integrated" == "false" ]]; then
613
601
  print_info "Shell integration not detected"
614
602
  local install_shell
615
- read -r -p "Install Worktrunk shell integration (enables 'wt switch' to change directories)? [Y/n]: " install_shell
603
+ setup_prompt install_shell "Install Worktrunk shell integration (enables 'wt switch' to change directories)? [Y/n]: " "Y"
616
604
  if [[ "$install_shell" =~ ^[Yy]?$ ]]; then
617
605
  _setup_worktrunk_shell_integration
618
606
  fi
@@ -625,7 +613,7 @@ _check_worktrunk_shell_integration() {
625
613
  # Install Worktrunk via Homebrew and set up shell integration.
626
614
  _install_worktrunk_brew() {
627
615
  local install_wt
628
- read -r -p "Install Worktrunk via Homebrew? [Y/n]: " install_wt
616
+ setup_prompt install_wt "Install Worktrunk via Homebrew? [Y/n]: " "Y"
629
617
 
630
618
  if [[ "$install_wt" =~ ^[Yy]?$ ]]; then
631
619
  if run_with_spinner "Installing Worktrunk via Homebrew" brew install max-sixty/worktrunk/wt; then
@@ -652,7 +640,7 @@ _install_worktrunk_brew() {
652
640
  # Install Worktrunk via Cargo and set up shell integration.
653
641
  _install_worktrunk_cargo() {
654
642
  local install_wt
655
- read -r -p "Install Worktrunk via Cargo? [Y/n]: " install_wt
643
+ setup_prompt install_wt "Install Worktrunk via Cargo? [Y/n]: " "Y"
656
644
 
657
645
  if [[ "$install_wt" =~ ^[Yy]?$ ]]; then
658
646
  if run_with_spinner "Installing Worktrunk via Cargo" cargo install worktrunk; then
@@ -714,7 +702,7 @@ setup_worktrunk() {
714
702
  # Trigger OpenCode extension install in Zed via the zed:// URI scheme.
715
703
  _install_opencode_ext_for_zed() {
716
704
  local install_opencode_ext
717
- read -r -p "Install OpenCode extension for Zed? [Y/n]: " install_opencode_ext
705
+ setup_prompt install_opencode_ext "Install OpenCode extension for Zed? [Y/n]: " "Y"
718
706
  if [[ "$install_opencode_ext" =~ ^[Yy]?$ ]]; then
719
707
  print_info "Installing OpenCode extension..."
720
708
  if [[ "$(uname)" == "Darwin" ]]; then
@@ -789,7 +777,7 @@ _install_tabby_linux() {
789
777
  # Offer and perform Tabby terminal installation.
790
778
  _install_tabby() {
791
779
  local install_tabby
792
- read -r -p "Install Tabby terminal? [Y/n]: " install_tabby
780
+ setup_prompt install_tabby "Install Tabby terminal? [Y/n]: " "Y"
793
781
 
794
782
  if [[ "$install_tabby" =~ ^[Yy]?$ ]]; then
795
783
  if [[ "$(uname)" == "Darwin" ]]; then
@@ -816,7 +804,7 @@ _install_tabby() {
816
804
  # Offer and perform Zed editor installation, then optionally install OpenCode extension.
817
805
  _install_zed_and_opencode_ext() {
818
806
  local install_zed
819
- read -r -p "Install Zed editor? [Y/n]: " install_zed
807
+ setup_prompt install_zed "Install Zed editor? [Y/n]: " "Y"
820
808
 
821
809
  if [[ "$install_zed" =~ ^[Yy]?$ ]]; then
822
810
  local zed_installed=false
@@ -976,11 +964,7 @@ setup_cursor_cli() {
976
964
  echo ""
977
965
 
978
966
  local install_cursor
979
- if [[ "${NON_INTERACTIVE:-}" != "true" ]]; then
980
- read -r -p "Install Cursor CLI? [Y/n]: " install_cursor
981
- else
982
- install_cursor="Y"
983
- fi
967
+ setup_prompt install_cursor "Install Cursor CLI? [Y/n]: " "Y"
984
968
 
985
969
  if [[ "$install_cursor" =~ ^[Yy]?$ ]]; then
986
970
  print_info "Installing Cursor CLI..."
@@ -1071,7 +1055,7 @@ setup_minisim() {
1071
1055
  fi
1072
1056
 
1073
1057
  local install_minisim
1074
- read -r -p "Install MiniSim? [Y/n]: " install_minisim
1058
+ setup_prompt install_minisim "Install MiniSim? [Y/n]: " "Y"
1075
1059
 
1076
1060
  if [[ "$install_minisim" =~ ^[Yy]?$ ]]; then
1077
1061
  if run_with_spinner "Installing MiniSim" brew install --cask minisim; then
@@ -1118,7 +1102,7 @@ setup_claudebar() {
1118
1102
  echo ""
1119
1103
 
1120
1104
  local install_claudebar
1121
- read -r -p "Install ClaudeBar? [Y/n]: " install_claudebar
1105
+ setup_prompt install_claudebar "Install ClaudeBar? [Y/n]: " "Y"
1122
1106
 
1123
1107
  if [[ "$install_claudebar" =~ ^[Yy]?$ ]]; then
1124
1108
  if run_with_spinner "Installing ClaudeBar" brew install --cask claudebar; then
@@ -1141,10 +1125,23 @@ setup_ssh_key() {
1141
1125
 
1142
1126
  if [[ ! -f ~/.ssh/id_ed25519 ]]; then
1143
1127
  print_warning "Ed25519 SSH key not found"
1144
- read -r -p "Generate new Ed25519 SSH key? [Y/n]: " generate_key
1128
+
1129
+ # SSH key generation requires email input — skip in non-interactive mode
1130
+ if [[ "${NON_INTERACTIVE:-false}" == "true" ]] || [[ ! -t 0 ]]; then
1131
+ print_info "Skipping SSH key generation (non-interactive mode)"
1132
+ return 0
1133
+ fi
1134
+
1135
+ local generate_key
1136
+ setup_prompt generate_key "Generate new Ed25519 SSH key? [Y/n]: " "Y"
1145
1137
 
1146
1138
  if [[ "$generate_key" =~ ^[Yy]?$ ]]; then
1147
- read -r -p "Enter your email address: " email
1139
+ local email
1140
+ setup_prompt email "Enter your email address: " ""
1141
+ if [[ -z "$email" ]]; then
1142
+ print_warning "No email provided — skipping SSH key generation"
1143
+ return 0
1144
+ fi
1148
1145
  install -d -m 700 ~/.ssh
1149
1146
  ssh-keygen -t ed25519 -C "$email" -f ~/.ssh/id_ed25519
1150
1147
  print_success "SSH key generated"
@@ -1420,10 +1417,10 @@ setup_nodejs() {
1420
1417
  local pkg_manager
1421
1418
  pkg_manager=$(detect_package_manager)
1422
1419
 
1420
+ local install_node
1423
1421
  case "$pkg_manager" in
1424
1422
  brew)
1425
- local install_node
1426
- read -r -p "Install Node.js via Homebrew? [Y/n]: " install_node
1423
+ setup_prompt install_node "Install Node.js via Homebrew? [Y/n]: " "Y"
1427
1424
  if [[ "$install_node" =~ ^[Yy]?$ ]]; then
1428
1425
  if run_with_spinner "Installing Node.js" brew install node; then
1429
1426
  print_success "Node.js installed: $(node --version)"
@@ -1433,15 +1430,13 @@ setup_nodejs() {
1433
1430
  fi
1434
1431
  ;;
1435
1432
  apt)
1436
- local install_node
1437
- read -r -p "Install Node.js via apt? [Y/n]: " install_node
1433
+ setup_prompt install_node "Install Node.js via apt? [Y/n]: " "Y"
1438
1434
  if [[ "$install_node" =~ ^[Yy]?$ ]]; then
1439
1435
  _install_nodejs_apt
1440
1436
  fi
1441
1437
  ;;
1442
1438
  dnf | yum)
1443
- local install_node
1444
- read -r -p "Install Node.js via $pkg_manager? [Y/n]: " install_node
1439
+ setup_prompt install_node "Install Node.js via $pkg_manager? [Y/n]: " "Y"
1445
1440
  if [[ "$install_node" =~ ^[Yy]?$ ]]; then
1446
1441
  if sudo "$pkg_manager" install -y nodejs npm; then
1447
1442
  print_success "Node.js installed: $(node --version)"
@@ -1451,8 +1446,7 @@ setup_nodejs() {
1451
1446
  fi
1452
1447
  ;;
1453
1448
  pacman)
1454
- local install_node
1455
- read -r -p "Install Node.js via pacman? [Y/n]: " install_node
1449
+ setup_prompt install_node "Install Node.js via pacman? [Y/n]: " "Y"
1456
1450
  if [[ "$install_node" =~ ^[Yy]?$ ]]; then
1457
1451
  if sudo pacman -S --noconfirm nodejs npm; then
1458
1452
  print_success "Node.js installed: $(node --version)"
@@ -1462,8 +1456,7 @@ setup_nodejs() {
1462
1456
  fi
1463
1457
  ;;
1464
1458
  apk)
1465
- local install_node
1466
- read -r -p "Install Node.js via apk? [Y/n]: " install_node
1459
+ setup_prompt install_node "Install Node.js via apk? [Y/n]: " "Y"
1467
1460
  if [[ "$install_node" =~ ^[Yy]?$ ]]; then
1468
1461
  if sudo apk add nodejs npm; then
1469
1462
  print_success "Node.js installed: $(node --version)"
@@ -1510,10 +1503,8 @@ setup_opencode_cli() {
1510
1503
  echo " It provides an AI-powered terminal interface for development tasks."
1511
1504
  echo ""
1512
1505
 
1513
- local install_oc="Y"
1514
- if [[ "$NON_INTERACTIVE" != "true" ]]; then
1515
- read -r -p "Install OpenCode via $installer? [Y/n]: " install_oc || install_oc="Y"
1516
- fi
1506
+ local install_oc
1507
+ setup_prompt install_oc "Install OpenCode via $installer? [Y/n]: " "Y"
1517
1508
  if [[ "$install_oc" =~ ^[Yy]?$ ]]; then
1518
1509
  if run_with_spinner "Installing OpenCode" npm_global_install "$install_pkg"; then
1519
1510
  print_success "OpenCode installed"
@@ -1566,10 +1557,8 @@ setup_codex_cli() {
1566
1557
  echo " It provides an AI-powered terminal interface using OpenAI models."
1567
1558
  echo ""
1568
1559
 
1569
- local install_codex="Y"
1570
- if [[ "${NON_INTERACTIVE:-}" != "true" ]]; then
1571
- read -r -p "Install Codex via $installer? [Y/n]: " install_codex || install_codex="Y"
1572
- fi
1560
+ local install_codex
1561
+ setup_prompt install_codex "Install Codex via $installer? [Y/n]: " "Y"
1573
1562
  if [[ "$install_codex" =~ ^[Yy]?$ ]]; then
1574
1563
  if run_with_spinner "Installing Codex" npm_global_install "$install_pkg"; then
1575
1564
  print_success "Codex installed"
@@ -1651,10 +1640,8 @@ setup_droid_cli() {
1651
1640
  echo " It provides autonomous coding capabilities with Factory.AI models."
1652
1641
  echo ""
1653
1642
 
1654
- local install_droid="Y"
1655
- if [[ "${NON_INTERACTIVE:-}" != "true" ]]; then
1656
- read -r -p "Install Droid CLI? [Y/n]: " install_droid || install_droid="Y"
1657
- fi
1643
+ local install_droid
1644
+ setup_prompt install_droid "Install Droid CLI? [Y/n]: " "Y"
1658
1645
  if [[ "$install_droid" =~ ^[Yy]?$ ]]; then
1659
1646
  print_info "Installing Droid CLI..."
1660
1647
  if command -v curl >/dev/null 2>&1; then
@@ -1708,10 +1695,8 @@ setup_google_workspace_cli() {
1708
1695
  echo " Used by Email, Business, and Accounts agents for Google Workspace integration."
1709
1696
  echo ""
1710
1697
 
1711
- local install_gws="Y"
1712
- if [[ "$NON_INTERACTIVE" != "true" ]]; then
1713
- read -r -p "Install Google Workspace CLI via $installer? [Y/n]: " install_gws || install_gws="Y"
1714
- fi
1698
+ local install_gws
1699
+ setup_prompt install_gws "Install Google Workspace CLI via $installer? [Y/n]: " "Y"
1715
1700
  if [[ "$install_gws" =~ ^[Yy]?$ ]]; then
1716
1701
  if run_with_spinner "Installing Google Workspace CLI" npm_global_install "$install_pkg"; then
1717
1702
  print_success "Google Workspace CLI installed"
@@ -1755,7 +1740,7 @@ setup_orbstack_vm() {
1755
1740
  return 0
1756
1741
  fi
1757
1742
 
1758
- read -r -p "Install OrbStack? [y/N]: " install_orb
1743
+ setup_prompt install_orb "Install OrbStack? [y/N]: " "n"
1759
1744
  if [[ "$install_orb" =~ ^[Yy]$ ]]; then
1760
1745
  if run_with_spinner "Installing OrbStack" brew install --cask orbstack; then
1761
1746
  print_success "OrbStack installed"
package/setup.sh CHANGED
@@ -10,7 +10,7 @@ shopt -s inherit_errexit 2>/dev/null || true
10
10
  # AI Assistant Server Access Framework Setup Script
11
11
  # Helps developers set up the framework for their infrastructure
12
12
  #
13
- # Version: 3.5.179
13
+ # Version: 3.5.181
14
14
  #
15
15
  # Quick Install:
16
16
  # npm install -g aidevops && aidevops update (recommended)
@@ -422,6 +422,31 @@ npm_global_install() {
422
422
  fi
423
423
  }
424
424
 
425
+ # Prompt the user for input, with non-interactive fallback.
426
+ # Canonical definition in .agents/scripts/setup/_common.sh; this fallback
427
+ # ensures the function exists even when _common.sh was not sourced (e.g.
428
+ # bootstrap from curl where setup-modules/ doesn't exist yet).
429
+ if ! type setup_prompt &>/dev/null; then
430
+ setup_prompt() {
431
+ local var_name="$1"
432
+ local prompt_text="$2"
433
+ local default_value="${3:-}"
434
+
435
+ # Non-interactive: use default without prompting
436
+ if [[ "${NON_INTERACTIVE:-false}" == "true" ]] || [[ ! -t 0 ]]; then
437
+ # shellcheck disable=SC2059 # var_name is a variable name, not a format string
438
+ printf -v "$var_name" '%s' "$default_value"
439
+ return 0
440
+ fi
441
+
442
+ local _setup_prompt_reply=""
443
+ read -r -p "$prompt_text" _setup_prompt_reply || _setup_prompt_reply="$default_value"
444
+ # shellcheck disable=SC2059 # var_name is a variable name, not a format string
445
+ printf -v "$var_name" '%s' "$_setup_prompt_reply"
446
+ return 0
447
+ }
448
+ fi
449
+
425
450
  # Confirm step in interactive mode
426
451
  # Usage: confirm_step "Step description" && function_to_run
427
452
  # Returns: 0 if confirmed or not interactive, 1 if skipped