aidevops 3.1.117 → 3.1.119
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 +1 -1
- package/aidevops.sh +1 -1
- package/package.json +1 -1
- package/setup-modules/post-setup.sh +167 -0
- package/setup-modules/schedulers.sh +1018 -0
- package/setup.sh +19 -1061
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.1.
|
|
13
|
+
# Version: 3.1.119
|
|
14
14
|
#
|
|
15
15
|
# Quick Install:
|
|
16
16
|
# npm install -g aidevops && aidevops update (recommended)
|
|
@@ -617,6 +617,10 @@ source "$(dirname "${BASH_SOURCE[0]}")/setup-modules/agent-deploy.sh"
|
|
|
617
617
|
source "$(dirname "${BASH_SOURCE[0]}")/setup-modules/config.sh"
|
|
618
618
|
# shellcheck disable=SC1091
|
|
619
619
|
source "$(dirname "${BASH_SOURCE[0]}")/setup-modules/plugins.sh"
|
|
620
|
+
# shellcheck disable=SC1091
|
|
621
|
+
source "$(dirname "${BASH_SOURCE[0]}")/setup-modules/schedulers.sh"
|
|
622
|
+
# shellcheck disable=SC1091
|
|
623
|
+
source "$(dirname "${BASH_SOURCE[0]}")/setup-modules/post-setup.sh"
|
|
620
624
|
|
|
621
625
|
parse_args() {
|
|
622
626
|
while [[ $# -gt 0 ]]; do
|
|
@@ -863,1040 +867,19 @@ main() {
|
|
|
863
867
|
echo ""
|
|
864
868
|
print_success "Setup complete!"
|
|
865
869
|
|
|
866
|
-
#
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
"aidevops auto-update enable"; then
|
|
880
|
-
_auto_update_installed=true
|
|
881
|
-
fi
|
|
882
|
-
if [[ "$_auto_update_installed" == "false" ]]; then
|
|
883
|
-
if [[ "$NON_INTERACTIVE" == "true" ]]; then
|
|
884
|
-
# Non-interactive: enable silently
|
|
885
|
-
bash "$auto_update_script" enable >/dev/null 2>&1 || true
|
|
886
|
-
print_info "Auto-update enabled (every 10 min). Disable: aidevops auto-update disable"
|
|
887
|
-
else
|
|
888
|
-
echo ""
|
|
889
|
-
echo "Auto-update keeps aidevops current by checking every 10 minutes."
|
|
890
|
-
echo "Safe to run while AI sessions are active."
|
|
891
|
-
echo ""
|
|
892
|
-
read -r -p "Enable auto-update? [Y/n]: " enable_auto
|
|
893
|
-
if [[ "$enable_auto" =~ ^[Yy]?$ || -z "$enable_auto" ]]; then
|
|
894
|
-
bash "$auto_update_script" enable
|
|
895
|
-
else
|
|
896
|
-
print_info "Skipped. Enable later: aidevops auto-update enable"
|
|
897
|
-
fi
|
|
898
|
-
fi
|
|
899
|
-
fi
|
|
900
|
-
fi
|
|
901
|
-
|
|
902
|
-
# Supervisor pulse scheduler — consent-gated autonomous orchestration.
|
|
903
|
-
# Uses pulse-wrapper.sh which handles dedup, orphan cleanup, and RAM-based concurrency.
|
|
904
|
-
# macOS: launchd plist invoking wrapper | Linux: cron entry invoking wrapper
|
|
905
|
-
# The plist is ALWAYS regenerated on setup.sh to pick up config changes (env vars,
|
|
906
|
-
# thresholds). Only the first-install prompt is gated on consent state.
|
|
907
|
-
#
|
|
908
|
-
# Ensure crontab has a global PATH= line (Linux only; macOS uses launchd env).
|
|
909
|
-
# Must run before any cron entries are installed so they inherit the PATH.
|
|
910
|
-
if [[ "$_os" != "Darwin" ]]; then
|
|
911
|
-
_ensure_cron_path
|
|
912
|
-
fi
|
|
913
|
-
|
|
914
|
-
# Consent model (GH#2926):
|
|
915
|
-
# - Default OFF: supervisor_pulse defaults to false in all config layers
|
|
916
|
-
# - Explicit consent required: user must type "y" (prompt defaults to [y/N])
|
|
917
|
-
# - Consent persisted: written to config.jsonc so it survives updates
|
|
918
|
-
# - Never silently re-enabled: if config says false, skip entirely
|
|
919
|
-
# - Non-interactive: only installs if config explicitly says true
|
|
920
|
-
local wrapper_script="$HOME/.aidevops/agents/scripts/pulse-wrapper.sh"
|
|
921
|
-
local pulse_label="com.aidevops.aidevops-supervisor-pulse"
|
|
922
|
-
# Read explicit user consent from config.jsonc (not merged defaults).
|
|
923
|
-
# Empty = user never configured this; "true"/"false" = explicit choice.
|
|
924
|
-
local _pulse_user_config=""
|
|
925
|
-
if type _jsonc_get_raw &>/dev/null && [[ -f "${JSONC_USER:-$HOME/.config/aidevops/config.jsonc}" ]]; then
|
|
926
|
-
_pulse_user_config=$(_jsonc_get_raw "${JSONC_USER:-$HOME/.config/aidevops/config.jsonc}" "orchestration.supervisor_pulse")
|
|
927
|
-
fi
|
|
928
|
-
|
|
929
|
-
# Also check legacy .conf user override
|
|
930
|
-
if [[ -z "$_pulse_user_config" && -f "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}" ]]; then
|
|
931
|
-
local _legacy_val
|
|
932
|
-
# Use awk instead of grep|tail|cut — grep exits 1 on no match, which
|
|
933
|
-
# aborts the script under set -euo pipefail. awk always exits 0.
|
|
934
|
-
_legacy_val=$(awk -F= '/^supervisor_pulse=/{val=$2} END{print val}' "${FEATURE_TOGGLES_USER:-$HOME/.config/aidevops/feature-toggles.conf}")
|
|
935
|
-
if [[ -n "$_legacy_val" ]]; then
|
|
936
|
-
_pulse_user_config="$_legacy_val"
|
|
937
|
-
fi
|
|
938
|
-
fi
|
|
939
|
-
|
|
940
|
-
# Also check env var override (highest priority)
|
|
941
|
-
if [[ -n "${AIDEVOPS_SUPERVISOR_PULSE:-}" ]]; then
|
|
942
|
-
_pulse_user_config="$AIDEVOPS_SUPERVISOR_PULSE"
|
|
943
|
-
fi
|
|
944
|
-
|
|
945
|
-
# Determine action based on consent state
|
|
946
|
-
local _do_install=false
|
|
947
|
-
local _pulse_lower
|
|
948
|
-
_pulse_lower=$(echo "$_pulse_user_config" | tr '[:upper:]' '[:lower:]')
|
|
949
|
-
|
|
950
|
-
if [[ "$_pulse_lower" == "false" ]]; then
|
|
951
|
-
# User explicitly declined — never prompt, never install
|
|
952
|
-
_do_install=false
|
|
953
|
-
elif [[ "$_pulse_lower" == "true" ]]; then
|
|
954
|
-
# User explicitly consented — install/regenerate
|
|
955
|
-
_do_install=true
|
|
956
|
-
elif [[ -z "$_pulse_user_config" ]]; then
|
|
957
|
-
# No explicit config — fresh install or never configured
|
|
958
|
-
if [[ "$NON_INTERACTIVE" == "true" ]]; then
|
|
959
|
-
# Non-interactive: default OFF, do not install without consent
|
|
960
|
-
_do_install=false
|
|
961
|
-
elif [[ -f "$wrapper_script" ]]; then
|
|
962
|
-
# Interactive: prompt with default-no
|
|
963
|
-
echo ""
|
|
964
|
-
echo "The supervisor pulse enables autonomous orchestration."
|
|
965
|
-
echo "It will act under your GitHub identity and consume API credits:"
|
|
966
|
-
echo " - Dispatches AI workers to implement tasks from GitHub issues"
|
|
967
|
-
echo " - Creates PRs, merges passing PRs, files improvement issues"
|
|
968
|
-
echo " - 4-hourly strategic review (opus-tier) for queue health"
|
|
969
|
-
echo " - Circuit breaker pauses dispatch on consecutive failures"
|
|
970
|
-
echo ""
|
|
971
|
-
read -r -p "Enable supervisor pulse? [y/N]: " enable_pulse
|
|
972
|
-
if [[ "$enable_pulse" =~ ^[Yy]$ ]]; then
|
|
973
|
-
_do_install=true
|
|
974
|
-
# Record explicit consent
|
|
975
|
-
if type cmd_set &>/dev/null; then
|
|
976
|
-
cmd_set "orchestration.supervisor_pulse" "true" || true
|
|
977
|
-
fi
|
|
978
|
-
else
|
|
979
|
-
_do_install=false
|
|
980
|
-
# Record explicit decline so we never re-prompt on updates
|
|
981
|
-
if type cmd_set &>/dev/null; then
|
|
982
|
-
cmd_set "orchestration.supervisor_pulse" "false" || true
|
|
983
|
-
fi
|
|
984
|
-
print_info "Skipped. Enable later: aidevops config set orchestration.supervisor_pulse true && ./setup.sh"
|
|
985
|
-
fi
|
|
986
|
-
fi
|
|
987
|
-
fi
|
|
988
|
-
|
|
989
|
-
# Guard: wrapper must exist
|
|
990
|
-
if [[ "$_do_install" == "true" && ! -f "$wrapper_script" ]]; then
|
|
991
|
-
# Wrapper not deployed yet — skip (will install on next run after rsync)
|
|
992
|
-
_do_install=false
|
|
993
|
-
fi
|
|
994
|
-
|
|
995
|
-
# Detect if pulse is already installed (for upgrade messaging)
|
|
996
|
-
# Uses shared helper to check both launchd and cron consistently
|
|
997
|
-
local _pulse_installed=false
|
|
998
|
-
if _scheduler_detect_installed \
|
|
999
|
-
"Supervisor pulse" \
|
|
1000
|
-
"$pulse_label" \
|
|
1001
|
-
"" \
|
|
1002
|
-
"pulse-wrapper" \
|
|
1003
|
-
"" \
|
|
1004
|
-
"" \
|
|
1005
|
-
""; then
|
|
1006
|
-
_pulse_installed=true
|
|
1007
|
-
fi
|
|
1008
|
-
|
|
1009
|
-
# Detect opencode binary location
|
|
1010
|
-
local opencode_bin
|
|
1011
|
-
opencode_bin=$(command -v opencode 2>/dev/null || echo "/opt/homebrew/bin/opencode")
|
|
1012
|
-
|
|
1013
|
-
if [[ "$_do_install" == "true" ]]; then
|
|
1014
|
-
mkdir -p "$HOME/.aidevops/logs"
|
|
1015
|
-
|
|
1016
|
-
if [[ "$_os" == "Darwin" ]]; then
|
|
1017
|
-
# macOS: use launchd plist with wrapper
|
|
1018
|
-
local pulse_plist="$HOME/Library/LaunchAgents/${pulse_label}.plist"
|
|
1019
|
-
|
|
1020
|
-
# Unload old plist if upgrading
|
|
1021
|
-
if _launchd_has_agent "$pulse_label"; then
|
|
1022
|
-
launchctl unload "$pulse_plist" || true
|
|
1023
|
-
pkill -f 'Supervisor Pulse' 2>/dev/null || true
|
|
1024
|
-
fi
|
|
1025
|
-
|
|
1026
|
-
# Also clean up old label if present
|
|
1027
|
-
local old_plist="$HOME/Library/LaunchAgents/com.aidevops.supervisor-pulse.plist"
|
|
1028
|
-
if [[ -f "$old_plist" ]]; then
|
|
1029
|
-
launchctl unload "$old_plist" || true
|
|
1030
|
-
rm -f "$old_plist"
|
|
1031
|
-
fi
|
|
1032
|
-
|
|
1033
|
-
# XML-escape paths for safe plist embedding (prevents injection
|
|
1034
|
-
# if $HOME or paths contain &, <, > characters)
|
|
1035
|
-
local _xml_wrapper_script _xml_home _xml_opencode_bin _xml_pulse_dir _xml_path
|
|
1036
|
-
local _headless_xml_env=""
|
|
1037
|
-
_xml_wrapper_script=$(_xml_escape "$wrapper_script")
|
|
1038
|
-
_xml_home=$(_xml_escape "$HOME")
|
|
1039
|
-
_xml_opencode_bin=$(_xml_escape "$opencode_bin")
|
|
1040
|
-
# Use neutral workspace path for PULSE_DIR so supervisor sessions
|
|
1041
|
-
# are not associated with any specific managed repo (GH#5136).
|
|
1042
|
-
_xml_pulse_dir=$(_xml_escape "${HOME}/.aidevops/.agent-workspace")
|
|
1043
|
-
_xml_path=$(_xml_escape "$PATH")
|
|
1044
|
-
if [[ -n "${AIDEVOPS_HEADLESS_MODELS:-}" ]]; then
|
|
1045
|
-
local _xml_headless_models
|
|
1046
|
-
_xml_headless_models=$(_xml_escape "$AIDEVOPS_HEADLESS_MODELS")
|
|
1047
|
-
_headless_xml_env+=$'\n'
|
|
1048
|
-
_headless_xml_env+=$'\t\t<key>AIDEVOPS_HEADLESS_MODELS</key>'
|
|
1049
|
-
_headless_xml_env+=$'\n'
|
|
1050
|
-
_headless_xml_env+=$'\t\t'"<string>${_xml_headless_models}</string>"
|
|
1051
|
-
fi
|
|
1052
|
-
if [[ -n "${AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST:-}" ]]; then
|
|
1053
|
-
local _xml_headless_allowlist
|
|
1054
|
-
_xml_headless_allowlist=$(_xml_escape "$AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST")
|
|
1055
|
-
_headless_xml_env+=$'\n'
|
|
1056
|
-
_headless_xml_env+=$'\t\t<key>AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST</key>'
|
|
1057
|
-
_headless_xml_env+=$'\n'
|
|
1058
|
-
_headless_xml_env+=$'\t\t'"<string>${_xml_headless_allowlist}</string>"
|
|
1059
|
-
fi
|
|
1060
|
-
|
|
1061
|
-
# Write the plist (always regenerated to pick up config changes)
|
|
1062
|
-
cat >"$pulse_plist" <<PLIST
|
|
1063
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1064
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1065
|
-
<plist version="1.0">
|
|
1066
|
-
<dict>
|
|
1067
|
-
<key>Label</key>
|
|
1068
|
-
<string>${pulse_label}</string>
|
|
1069
|
-
<key>ProgramArguments</key>
|
|
1070
|
-
<array>
|
|
1071
|
-
<string>/bin/bash</string>
|
|
1072
|
-
<string>${_xml_wrapper_script}</string>
|
|
1073
|
-
</array>
|
|
1074
|
-
<key>StartInterval</key>
|
|
1075
|
-
<integer>120</integer>
|
|
1076
|
-
<key>StandardOutPath</key>
|
|
1077
|
-
<string>${_xml_home}/.aidevops/logs/pulse-wrapper.log</string>
|
|
1078
|
-
<key>StandardErrorPath</key>
|
|
1079
|
-
<string>${_xml_home}/.aidevops/logs/pulse-wrapper.log</string>
|
|
1080
|
-
<key>EnvironmentVariables</key>
|
|
1081
|
-
<dict>
|
|
1082
|
-
<key>PATH</key>
|
|
1083
|
-
<string>${_xml_path}</string>
|
|
1084
|
-
<key>HOME</key>
|
|
1085
|
-
<string>${_xml_home}</string>
|
|
1086
|
-
<key>OPENCODE_BIN</key>
|
|
1087
|
-
<string>${_xml_opencode_bin}</string>
|
|
1088
|
-
<key>PULSE_DIR</key>
|
|
1089
|
-
<string>${_xml_pulse_dir}</string>
|
|
1090
|
-
<key>PULSE_STALE_THRESHOLD</key>
|
|
1091
|
-
<string>1800</string>
|
|
1092
|
-
${_headless_xml_env}
|
|
1093
|
-
</dict>
|
|
1094
|
-
<key>RunAtLoad</key>
|
|
1095
|
-
<true/>
|
|
1096
|
-
<key>KeepAlive</key>
|
|
1097
|
-
<false/>
|
|
1098
|
-
</dict>
|
|
1099
|
-
</plist>
|
|
1100
|
-
PLIST
|
|
1101
|
-
|
|
1102
|
-
if launchctl load "$pulse_plist"; then
|
|
1103
|
-
if [[ "$_pulse_installed" == "true" ]]; then
|
|
1104
|
-
print_info "Supervisor pulse updated (launchd config regenerated)"
|
|
1105
|
-
else
|
|
1106
|
-
print_info "Supervisor pulse enabled (launchd, every 2 min)"
|
|
1107
|
-
fi
|
|
1108
|
-
else
|
|
1109
|
-
print_warning "Failed to load supervisor pulse LaunchAgent"
|
|
1110
|
-
fi
|
|
1111
|
-
else
|
|
1112
|
-
# Linux: use cron entry with wrapper
|
|
1113
|
-
# Remove old-style cron entries (direct opencode invocation)
|
|
1114
|
-
# Shell-escape all interpolated paths to prevent command injection
|
|
1115
|
-
# via $(…) or backticks if paths contain shell metacharacters
|
|
1116
|
-
# PATH is managed globally by _ensure_cron_path() — do NOT set inline
|
|
1117
|
-
# PATH= here, it overrides the global line and breaks nvm/bun/cargo.
|
|
1118
|
-
# OPENCODE_BIN removed — resolved from PATH at runtime via command -v.
|
|
1119
|
-
# See #4099 and #4240 for history.
|
|
1120
|
-
local _cron_pulse_dir _cron_wrapper_script _cron_headless_env=""
|
|
1121
|
-
# Use neutral workspace path for PULSE_DIR (GH#5136)
|
|
1122
|
-
_cron_pulse_dir=$(_cron_escape "${HOME}/.aidevops/.agent-workspace")
|
|
1123
|
-
_cron_wrapper_script=$(_cron_escape "$wrapper_script")
|
|
1124
|
-
if [[ -n "${AIDEVOPS_HEADLESS_MODELS:-}" ]]; then
|
|
1125
|
-
local _cron_headless_models
|
|
1126
|
-
_cron_headless_models=$(_cron_escape "$AIDEVOPS_HEADLESS_MODELS")
|
|
1127
|
-
_cron_headless_env+=" AIDEVOPS_HEADLESS_MODELS=${_cron_headless_models}"
|
|
1128
|
-
fi
|
|
1129
|
-
if [[ -n "${AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST:-}" ]]; then
|
|
1130
|
-
local _cron_headless_allowlist
|
|
1131
|
-
_cron_headless_allowlist=$(_cron_escape "$AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST")
|
|
1132
|
-
_cron_headless_env+=" AIDEVOPS_HEADLESS_PROVIDER_ALLOWLIST=${_cron_headless_allowlist}"
|
|
1133
|
-
fi
|
|
1134
|
-
(
|
|
1135
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: supervisor-pulse'
|
|
1136
|
-
echo "*/2 * * * * PULSE_DIR=${_cron_pulse_dir}${_cron_headless_env} /bin/bash ${_cron_wrapper_script} >> \"\$HOME/.aidevops/logs/pulse-wrapper.log\" 2>&1 # aidevops: supervisor-pulse"
|
|
1137
|
-
) | crontab - || true
|
|
1138
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: supervisor-pulse"; then
|
|
1139
|
-
print_info "Supervisor pulse enabled (cron, every 2 min). Disable: crontab -e and remove the supervisor-pulse line"
|
|
1140
|
-
else
|
|
1141
|
-
print_warning "Failed to install supervisor pulse cron entry. See runners.md for manual setup."
|
|
1142
|
-
fi
|
|
1143
|
-
fi
|
|
1144
|
-
elif [[ "$_pulse_lower" == "false" && "$_pulse_installed" == "true" ]]; then
|
|
1145
|
-
# User explicitly disabled but pulse is still installed — clean up
|
|
1146
|
-
if [[ "$_os" == "Darwin" ]]; then
|
|
1147
|
-
local pulse_plist="$HOME/Library/LaunchAgents/${pulse_label}.plist"
|
|
1148
|
-
if _launchd_has_agent "$pulse_label"; then
|
|
1149
|
-
launchctl unload "$pulse_plist" || true
|
|
1150
|
-
rm -f "$pulse_plist"
|
|
1151
|
-
pkill -f 'Supervisor Pulse' 2>/dev/null || true
|
|
1152
|
-
print_info "Supervisor pulse disabled (launchd agent removed per config)"
|
|
1153
|
-
fi
|
|
1154
|
-
else
|
|
1155
|
-
if crontab -l 2>/dev/null | grep -qF "pulse-wrapper"; then
|
|
1156
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: supervisor-pulse' | crontab - || true
|
|
1157
|
-
print_info "Supervisor pulse disabled (cron entry removed per config)"
|
|
1158
|
-
fi
|
|
1159
|
-
fi
|
|
1160
|
-
fi
|
|
1161
|
-
|
|
1162
|
-
# Enable stats-wrapper — runs quality sweep and health issue updates
|
|
1163
|
-
# separately from the pulse (t1429). Only installed when the supervisor
|
|
1164
|
-
# pulse is enabled (stats are useless without it).
|
|
1165
|
-
local stats_script="$HOME/.aidevops/agents/scripts/stats-wrapper.sh"
|
|
1166
|
-
local stats_label="com.aidevops.aidevops-stats-wrapper"
|
|
1167
|
-
if [[ -x "$stats_script" ]] && [[ "$_pulse_lower" == "true" ]]; then
|
|
1168
|
-
# Always regenerate to pick up config/format changes (matches pulse behavior)
|
|
1169
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1170
|
-
local stats_plist="$HOME/Library/LaunchAgents/${stats_label}.plist"
|
|
1171
|
-
|
|
1172
|
-
local _xml_stats_script _xml_stats_home _xml_stats_path
|
|
1173
|
-
_xml_stats_script=$(_xml_escape "$stats_script")
|
|
1174
|
-
_xml_stats_home=$(_xml_escape "$HOME")
|
|
1175
|
-
_xml_stats_path=$(_xml_escape "$PATH")
|
|
1176
|
-
local stats_plist_content
|
|
1177
|
-
stats_plist_content=$(
|
|
1178
|
-
cat <<PLIST
|
|
1179
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1180
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1181
|
-
<plist version="1.0">
|
|
1182
|
-
<dict>
|
|
1183
|
-
<key>Label</key>
|
|
1184
|
-
<string>${stats_label}</string>
|
|
1185
|
-
<key>ProgramArguments</key>
|
|
1186
|
-
<array>
|
|
1187
|
-
<string>/bin/bash</string>
|
|
1188
|
-
<string>${_xml_stats_script}</string>
|
|
1189
|
-
</array>
|
|
1190
|
-
<key>StartInterval</key>
|
|
1191
|
-
<integer>900</integer>
|
|
1192
|
-
<key>StandardOutPath</key>
|
|
1193
|
-
<string>${_xml_stats_home}/.aidevops/logs/stats.log</string>
|
|
1194
|
-
<key>StandardErrorPath</key>
|
|
1195
|
-
<string>${_xml_stats_home}/.aidevops/logs/stats.log</string>
|
|
1196
|
-
<key>EnvironmentVariables</key>
|
|
1197
|
-
<dict>
|
|
1198
|
-
<key>PATH</key>
|
|
1199
|
-
<string>${_xml_stats_path}</string>
|
|
1200
|
-
<key>HOME</key>
|
|
1201
|
-
<string>${_xml_stats_home}</string>
|
|
1202
|
-
</dict>
|
|
1203
|
-
<key>RunAtLoad</key>
|
|
1204
|
-
<true/>
|
|
1205
|
-
<key>KeepAlive</key>
|
|
1206
|
-
<false/>
|
|
1207
|
-
</dict>
|
|
1208
|
-
</plist>
|
|
1209
|
-
PLIST
|
|
1210
|
-
)
|
|
1211
|
-
if _launchd_install_if_changed "$stats_label" "$stats_plist" "$stats_plist_content"; then
|
|
1212
|
-
print_info "Stats wrapper enabled (launchd, every 15 min)"
|
|
1213
|
-
else
|
|
1214
|
-
print_warning "Failed to load stats wrapper LaunchAgent"
|
|
1215
|
-
fi
|
|
1216
|
-
else
|
|
1217
|
-
local _cron_stats_script
|
|
1218
|
-
_cron_stats_script=$(_cron_escape "$stats_script")
|
|
1219
|
-
(
|
|
1220
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: stats-wrapper'
|
|
1221
|
-
echo "*/15 * * * * /bin/bash ${_cron_stats_script} >> \"\$HOME/.aidevops/logs/stats.log\" 2>&1 # aidevops: stats-wrapper"
|
|
1222
|
-
) | crontab - || true
|
|
1223
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: stats-wrapper"; then
|
|
1224
|
-
print_info "Stats wrapper enabled (cron, every 15 min)"
|
|
1225
|
-
fi
|
|
1226
|
-
fi
|
|
1227
|
-
elif [[ "$_pulse_lower" == "false" ]]; then
|
|
1228
|
-
# Remove stats scheduler if pulse is disabled
|
|
1229
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1230
|
-
local stats_plist="$HOME/Library/LaunchAgents/${stats_label}.plist"
|
|
1231
|
-
if _launchd_has_agent "$stats_label"; then
|
|
1232
|
-
launchctl unload "$stats_plist" || true
|
|
1233
|
-
rm -f "$stats_plist"
|
|
1234
|
-
print_info "Stats wrapper disabled (launchd agent removed — pulse is off)"
|
|
1235
|
-
fi
|
|
1236
|
-
else
|
|
1237
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: stats-wrapper"; then
|
|
1238
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: stats-wrapper' | crontab - || true
|
|
1239
|
-
print_info "Stats wrapper disabled (cron entry removed — pulse is off)"
|
|
1240
|
-
fi
|
|
1241
|
-
fi
|
|
1242
|
-
fi
|
|
1243
|
-
|
|
1244
|
-
# Enable repo-sync scheduler if not already installed
|
|
1245
|
-
# Keeps local git repos up to date with daily ff-only pulls
|
|
1246
|
-
# Respects config: aidevops config set orchestration.repo_sync false
|
|
1247
|
-
local repo_sync_script="$HOME/.aidevops/agents/scripts/repo-sync-helper.sh"
|
|
1248
|
-
if [[ -x "$repo_sync_script" ]] && is_feature_enabled repo_sync 2>/dev/null; then
|
|
1249
|
-
local _repo_sync_installed=false
|
|
1250
|
-
if _launchd_has_agent "com.aidevops.aidevops-repo-sync"; then
|
|
1251
|
-
_repo_sync_installed=true
|
|
1252
|
-
elif crontab -l 2>/dev/null | grep -qF "aidevops-repo-sync"; then
|
|
1253
|
-
_repo_sync_installed=true
|
|
1254
|
-
fi
|
|
1255
|
-
if [[ "$_repo_sync_installed" == "false" ]]; then
|
|
1256
|
-
if [[ "$NON_INTERACTIVE" == "true" ]]; then
|
|
1257
|
-
bash "$repo_sync_script" enable >/dev/null 2>&1 || true
|
|
1258
|
-
print_info "Repo sync enabled (daily). Disable: aidevops repo-sync disable"
|
|
1259
|
-
else
|
|
1260
|
-
echo ""
|
|
1261
|
-
echo "Repo sync keeps your local git repos up to date by running"
|
|
1262
|
-
echo "git pull --ff-only daily on clean repos on their default branch."
|
|
1263
|
-
echo ""
|
|
1264
|
-
read -r -p "Enable daily repo sync? [Y/n]: " enable_repo_sync
|
|
1265
|
-
if [[ "$enable_repo_sync" =~ ^[Yy]?$ || -z "$enable_repo_sync" ]]; then
|
|
1266
|
-
bash "$repo_sync_script" enable
|
|
1267
|
-
else
|
|
1268
|
-
print_info "Skipped. Enable later: aidevops repo-sync enable"
|
|
1269
|
-
fi
|
|
1270
|
-
fi
|
|
1271
|
-
fi
|
|
1272
|
-
fi
|
|
1273
|
-
|
|
1274
|
-
# Process guard — kills runaway AI processes (ShellCheck bloat, stuck workers)
|
|
1275
|
-
# before they exhaust memory and cause kernel panics. Always installed when the
|
|
1276
|
-
# script exists; no consent needed (safety net, not autonomous action).
|
|
1277
|
-
# macOS: launchd plist (30s interval, RunAtLoad=true) | Linux: cron (every minute)
|
|
1278
|
-
local guard_script="$HOME/.aidevops/agents/scripts/process-guard-helper.sh"
|
|
1279
|
-
local guard_label="sh.aidevops.process-guard"
|
|
1280
|
-
if [[ -x "$guard_script" ]]; then
|
|
1281
|
-
mkdir -p "$HOME/.aidevops/logs"
|
|
1282
|
-
|
|
1283
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1284
|
-
local guard_plist="$HOME/Library/LaunchAgents/${guard_label}.plist"
|
|
1285
|
-
|
|
1286
|
-
# XML-escape paths for safe plist embedding (prevents injection
|
|
1287
|
-
# if $HOME or paths contain &, <, > characters)
|
|
1288
|
-
local _xml_guard_script _xml_guard_home _xml_guard_path
|
|
1289
|
-
_xml_guard_script=$(_xml_escape "$guard_script")
|
|
1290
|
-
_xml_guard_home=$(_xml_escape "$HOME")
|
|
1291
|
-
_xml_guard_path=$(_xml_escape "$PATH")
|
|
1292
|
-
|
|
1293
|
-
local guard_plist_content
|
|
1294
|
-
guard_plist_content=$(
|
|
1295
|
-
cat <<GUARD_PLIST
|
|
1296
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1297
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1298
|
-
<plist version="1.0">
|
|
1299
|
-
<dict>
|
|
1300
|
-
<key>Label</key>
|
|
1301
|
-
<string>${guard_label}</string>
|
|
1302
|
-
<key>ProgramArguments</key>
|
|
1303
|
-
<array>
|
|
1304
|
-
<string>/bin/bash</string>
|
|
1305
|
-
<string>${_xml_guard_script}</string>
|
|
1306
|
-
<string>kill-runaways</string>
|
|
1307
|
-
</array>
|
|
1308
|
-
<key>StartInterval</key>
|
|
1309
|
-
<integer>30</integer>
|
|
1310
|
-
<key>StandardOutPath</key>
|
|
1311
|
-
<string>${_xml_guard_home}/.aidevops/logs/process-guard.log</string>
|
|
1312
|
-
<key>StandardErrorPath</key>
|
|
1313
|
-
<string>${_xml_guard_home}/.aidevops/logs/process-guard.log</string>
|
|
1314
|
-
<key>EnvironmentVariables</key>
|
|
1315
|
-
<dict>
|
|
1316
|
-
<key>PATH</key>
|
|
1317
|
-
<string>${_xml_guard_path}</string>
|
|
1318
|
-
<key>HOME</key>
|
|
1319
|
-
<string>${_xml_guard_home}</string>
|
|
1320
|
-
<key>SHELLCHECK_RSS_LIMIT_KB</key>
|
|
1321
|
-
<string>524288</string>
|
|
1322
|
-
<key>SHELLCHECK_RUNTIME_LIMIT</key>
|
|
1323
|
-
<string>120</string>
|
|
1324
|
-
<key>CHILD_RSS_LIMIT_KB</key>
|
|
1325
|
-
<string>8388608</string>
|
|
1326
|
-
<key>CHILD_RUNTIME_LIMIT</key>
|
|
1327
|
-
<string>7200</string>
|
|
1328
|
-
</dict>
|
|
1329
|
-
<key>RunAtLoad</key>
|
|
1330
|
-
<true/>
|
|
1331
|
-
<key>KeepAlive</key>
|
|
1332
|
-
<false/>
|
|
1333
|
-
</dict>
|
|
1334
|
-
</plist>
|
|
1335
|
-
GUARD_PLIST
|
|
1336
|
-
)
|
|
1337
|
-
|
|
1338
|
-
if _launchd_install_if_changed "$guard_label" "$guard_plist" "$guard_plist_content"; then
|
|
1339
|
-
print_info "Process guard enabled (launchd, every 30s, survives reboot)"
|
|
1340
|
-
else
|
|
1341
|
-
print_warning "Failed to load process guard LaunchAgent"
|
|
1342
|
-
fi
|
|
1343
|
-
else
|
|
1344
|
-
# Linux: cron entry (every minute — cron minimum granularity)
|
|
1345
|
-
# Always regenerate to pick up config changes (matches macOS behavior)
|
|
1346
|
-
# Shell-escape path to prevent command injection via metacharacters
|
|
1347
|
-
local _cron_guard_script
|
|
1348
|
-
_cron_guard_script=$(_cron_escape "$guard_script")
|
|
1349
|
-
(
|
|
1350
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: process-guard'
|
|
1351
|
-
echo "* * * * * SHELLCHECK_RSS_LIMIT_KB=524288 SHELLCHECK_RUNTIME_LIMIT=120 CHILD_RSS_LIMIT_KB=8388608 CHILD_RUNTIME_LIMIT=7200 /bin/bash ${_cron_guard_script} kill-runaways >> \"\$HOME/.aidevops/logs/process-guard.log\" 2>&1 # aidevops: process-guard"
|
|
1352
|
-
) | crontab - || true
|
|
1353
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: process-guard"; then
|
|
1354
|
-
print_info "Process guard enabled (cron, every minute)"
|
|
1355
|
-
else
|
|
1356
|
-
print_warning "Failed to install process guard cron entry"
|
|
1357
|
-
fi
|
|
1358
|
-
fi
|
|
1359
|
-
fi
|
|
1360
|
-
|
|
1361
|
-
# Memory pressure monitor — process-focused memory watchdog (t1398.5, GH#2915).
|
|
1362
|
-
# Monitors individual process RSS, runtime, session count, and aggregate memory.
|
|
1363
|
-
# Auto-kills runaway ShellCheck (language server respawns them). Always installed
|
|
1364
|
-
# when the script exists; no consent needed (safety net, not autonomous action).
|
|
1365
|
-
# macOS: launchd plist (60s interval, RunAtLoad=true) | Linux: cron (every minute)
|
|
1366
|
-
local monitor_script="$HOME/.aidevops/agents/scripts/memory-pressure-monitor.sh"
|
|
1367
|
-
local monitor_label="sh.aidevops.memory-pressure-monitor"
|
|
1368
|
-
if [[ -x "$monitor_script" ]]; then
|
|
1369
|
-
mkdir -p "$HOME/.aidevops/logs"
|
|
1370
|
-
|
|
1371
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1372
|
-
local monitor_plist="$HOME/Library/LaunchAgents/${monitor_label}.plist"
|
|
1373
|
-
|
|
1374
|
-
local monitor_plist_content
|
|
1375
|
-
monitor_plist_content=$(
|
|
1376
|
-
cat <<MONITOR_PLIST
|
|
1377
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1378
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1379
|
-
<plist version="1.0">
|
|
1380
|
-
<dict>
|
|
1381
|
-
<key>Label</key>
|
|
1382
|
-
<string>${monitor_label}</string>
|
|
1383
|
-
<key>ProgramArguments</key>
|
|
1384
|
-
<array>
|
|
1385
|
-
<string>/bin/bash</string>
|
|
1386
|
-
<string>${monitor_script}</string>
|
|
1387
|
-
</array>
|
|
1388
|
-
<key>StartInterval</key>
|
|
1389
|
-
<integer>60</integer>
|
|
1390
|
-
<key>StandardOutPath</key>
|
|
1391
|
-
<string>${HOME}/.aidevops/logs/memory-pressure-launchd.log</string>
|
|
1392
|
-
<key>StandardErrorPath</key>
|
|
1393
|
-
<string>${HOME}/.aidevops/logs/memory-pressure-launchd.log</string>
|
|
1394
|
-
<key>EnvironmentVariables</key>
|
|
1395
|
-
<dict>
|
|
1396
|
-
<key>PATH</key>
|
|
1397
|
-
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
1398
|
-
<key>HOME</key>
|
|
1399
|
-
<string>${HOME}</string>
|
|
1400
|
-
</dict>
|
|
1401
|
-
<key>RunAtLoad</key>
|
|
1402
|
-
<true/>
|
|
1403
|
-
<key>KeepAlive</key>
|
|
1404
|
-
<false/>
|
|
1405
|
-
<key>ProcessType</key>
|
|
1406
|
-
<string>Background</string>
|
|
1407
|
-
<key>LowPriorityBackgroundIO</key>
|
|
1408
|
-
<true/>
|
|
1409
|
-
<key>Nice</key>
|
|
1410
|
-
<integer>10</integer>
|
|
1411
|
-
</dict>
|
|
1412
|
-
</plist>
|
|
1413
|
-
MONITOR_PLIST
|
|
1414
|
-
)
|
|
1415
|
-
|
|
1416
|
-
if _launchd_install_if_changed "$monitor_label" "$monitor_plist" "$monitor_plist_content"; then
|
|
1417
|
-
print_info "Memory pressure monitor enabled (launchd, every 60s, survives reboot)"
|
|
1418
|
-
else
|
|
1419
|
-
print_warning "Failed to load memory pressure monitor LaunchAgent"
|
|
1420
|
-
fi
|
|
1421
|
-
else
|
|
1422
|
-
# Linux: cron entry (every minute — cron minimum granularity)
|
|
1423
|
-
(
|
|
1424
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: memory-pressure-monitor'
|
|
1425
|
-
echo "* * * * * /bin/bash \"${monitor_script}\" >> \"\$HOME/.aidevops/logs/memory-pressure-launchd.log\" 2>&1 # aidevops: memory-pressure-monitor"
|
|
1426
|
-
) | crontab - 2>/dev/null || true
|
|
1427
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: memory-pressure-monitor" 2>/dev/null; then
|
|
1428
|
-
print_info "Memory pressure monitor enabled (cron, every minute)"
|
|
1429
|
-
else
|
|
1430
|
-
print_warning "Failed to install memory pressure monitor cron entry"
|
|
1431
|
-
fi
|
|
1432
|
-
fi
|
|
1433
|
-
fi
|
|
1434
|
-
|
|
1435
|
-
# Screen time snapshot — captures daily screen time for contributor stats.
|
|
1436
|
-
# Accumulates data in screen-time.jsonl (macOS Knowledge DB retains only ~28 days).
|
|
1437
|
-
# Always installed when the script exists; no consent needed (data collection only).
|
|
1438
|
-
# macOS: launchd plist (every 6h, RunAtLoad=true) | Linux: cron (every 6h)
|
|
1439
|
-
local st_script="$HOME/.aidevops/agents/scripts/screen-time-helper.sh"
|
|
1440
|
-
local st_label="sh.aidevops.screen-time-snapshot"
|
|
1441
|
-
if [[ -x "$st_script" ]]; then
|
|
1442
|
-
mkdir -p "$HOME/.aidevops/.agent-workspace/logs"
|
|
1443
|
-
|
|
1444
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1445
|
-
local st_plist="$HOME/Library/LaunchAgents/${st_label}.plist"
|
|
1446
|
-
|
|
1447
|
-
# XML-escape paths for safe plist embedding
|
|
1448
|
-
local _xml_st_script _xml_st_home
|
|
1449
|
-
_xml_st_script=$(_xml_escape "$st_script")
|
|
1450
|
-
_xml_st_home=$(_xml_escape "$HOME")
|
|
1451
|
-
|
|
1452
|
-
local st_plist_content
|
|
1453
|
-
st_plist_content=$(
|
|
1454
|
-
cat <<ST_PLIST
|
|
1455
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1456
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1457
|
-
<plist version="1.0">
|
|
1458
|
-
<dict>
|
|
1459
|
-
<key>Label</key>
|
|
1460
|
-
<string>${st_label}</string>
|
|
1461
|
-
<key>ProgramArguments</key>
|
|
1462
|
-
<array>
|
|
1463
|
-
<string>/bin/bash</string>
|
|
1464
|
-
<string>${_xml_st_script}</string>
|
|
1465
|
-
<string>snapshot</string>
|
|
1466
|
-
</array>
|
|
1467
|
-
<key>StartInterval</key>
|
|
1468
|
-
<integer>21600</integer>
|
|
1469
|
-
<key>StandardOutPath</key>
|
|
1470
|
-
<string>${_xml_st_home}/.aidevops/.agent-workspace/logs/screen-time-snapshot.log</string>
|
|
1471
|
-
<key>StandardErrorPath</key>
|
|
1472
|
-
<string>${_xml_st_home}/.aidevops/.agent-workspace/logs/screen-time-snapshot.log</string>
|
|
1473
|
-
<key>EnvironmentVariables</key>
|
|
1474
|
-
<dict>
|
|
1475
|
-
<key>PATH</key>
|
|
1476
|
-
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
1477
|
-
<key>HOME</key>
|
|
1478
|
-
<string>${_xml_st_home}</string>
|
|
1479
|
-
</dict>
|
|
1480
|
-
<key>RunAtLoad</key>
|
|
1481
|
-
<true/>
|
|
1482
|
-
<key>KeepAlive</key>
|
|
1483
|
-
<false/>
|
|
1484
|
-
<key>ProcessType</key>
|
|
1485
|
-
<string>Background</string>
|
|
1486
|
-
<key>LowPriorityBackgroundIO</key>
|
|
1487
|
-
<true/>
|
|
1488
|
-
<key>Nice</key>
|
|
1489
|
-
<integer>10</integer>
|
|
1490
|
-
</dict>
|
|
1491
|
-
</plist>
|
|
1492
|
-
ST_PLIST
|
|
1493
|
-
)
|
|
1494
|
-
|
|
1495
|
-
if _launchd_install_if_changed "$st_label" "$st_plist" "$st_plist_content"; then
|
|
1496
|
-
print_info "Screen time snapshot enabled (launchd, every 6h, survives reboot)"
|
|
1497
|
-
else
|
|
1498
|
-
print_warning "Failed to load screen time snapshot LaunchAgent"
|
|
1499
|
-
fi
|
|
1500
|
-
else
|
|
1501
|
-
# Linux: cron entry (every 6 hours)
|
|
1502
|
-
local _cron_st_script
|
|
1503
|
-
_cron_st_script=$(_cron_escape "$st_script")
|
|
1504
|
-
(
|
|
1505
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: screen-time-snapshot'
|
|
1506
|
-
echo "0 */6 * * * /bin/bash ${_cron_st_script} snapshot >> \"\$HOME/.aidevops/.agent-workspace/logs/screen-time-snapshot.log\" 2>&1 # aidevops: screen-time-snapshot"
|
|
1507
|
-
) | crontab - 2>/dev/null || true
|
|
1508
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: screen-time-snapshot" 2>/dev/null; then
|
|
1509
|
-
print_info "Screen time snapshot enabled (cron, every 6h)"
|
|
1510
|
-
else
|
|
1511
|
-
print_warning "Failed to install screen time snapshot cron entry"
|
|
1512
|
-
fi
|
|
1513
|
-
fi
|
|
1514
|
-
fi
|
|
1515
|
-
|
|
1516
|
-
# Contribution watch — monitors external issues/PRs for new activity (t1554).
|
|
1517
|
-
# Auto-seeds on first run (discovers authored/commented issues/PRs), then installs
|
|
1518
|
-
# a launchd/cron job to scan periodically. Requires gh CLI authenticated.
|
|
1519
|
-
# No consent needed — this is passive monitoring (read-only notifications API),
|
|
1520
|
-
# not autonomous action. Comment bodies are never processed by LLM in automated context.
|
|
1521
|
-
# Respects config: aidevops config set orchestration.contribution_watch false
|
|
1522
|
-
local cw_script="$HOME/.aidevops/agents/scripts/contribution-watch-helper.sh"
|
|
1523
|
-
local cw_label="sh.aidevops.contribution-watch"
|
|
1524
|
-
local cw_state="$HOME/.aidevops/cache/contribution-watch.json"
|
|
1525
|
-
if [[ -x "$cw_script" ]] && is_feature_enabled orchestration.contribution_watch 2>/dev/null && command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
|
|
1526
|
-
# Resolve log directory from config (paths.log_dir), expanding ~ to $HOME.
|
|
1527
|
-
# Falls back to the default if config is unavailable or jq is missing.
|
|
1528
|
-
# Validate before expansion to guard against shell metacharacter injection.
|
|
1529
|
-
local _cw_log_dir
|
|
1530
|
-
# shellcheck disable=SC2088 # Tilde is intentionally literal here; expanded below via ${/#\~/$HOME}
|
|
1531
|
-
if type _jsonc_get &>/dev/null; then
|
|
1532
|
-
_cw_log_dir=$(_jsonc_get "paths.log_dir" "~/.aidevops/logs")
|
|
1533
|
-
else
|
|
1534
|
-
_cw_log_dir="~/.aidevops/logs"
|
|
1535
|
-
fi
|
|
1536
|
-
if [[ "$_cw_log_dir" == *['`$']* ]]; then
|
|
1537
|
-
print_error "Invalid characters in paths.log_dir: $_cw_log_dir"
|
|
1538
|
-
return 1
|
|
1539
|
-
fi
|
|
1540
|
-
_cw_log_dir="${_cw_log_dir/#\~/$HOME}"
|
|
1541
|
-
mkdir -p "$HOME/.aidevops/cache" "$_cw_log_dir"
|
|
1542
|
-
|
|
1543
|
-
# Auto-seed on first run (populates state file with existing contributions)
|
|
1544
|
-
if [[ ! -f "$cw_state" ]]; then
|
|
1545
|
-
print_info "Discovering external contributions for contribution watch..."
|
|
1546
|
-
if bash "$cw_script" seed >/dev/null 2>&1; then
|
|
1547
|
-
print_info "Contribution watch seeded (external issues/PRs discovered)"
|
|
1548
|
-
else
|
|
1549
|
-
print_warning "Contribution watch seed failed (non-fatal, will retry on next run)"
|
|
1550
|
-
fi
|
|
1551
|
-
fi
|
|
1552
|
-
|
|
1553
|
-
# Install/update scheduled scanner
|
|
1554
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1555
|
-
local cw_plist="$HOME/Library/LaunchAgents/${cw_label}.plist"
|
|
1556
|
-
|
|
1557
|
-
local _xml_cw_script _xml_cw_home _xml_cw_log_dir
|
|
1558
|
-
_xml_cw_script=$(_xml_escape "$cw_script")
|
|
1559
|
-
_xml_cw_home=$(_xml_escape "$HOME")
|
|
1560
|
-
_xml_cw_log_dir=$(_xml_escape "$_cw_log_dir")
|
|
1561
|
-
|
|
1562
|
-
local cw_plist_content
|
|
1563
|
-
cw_plist_content=$(
|
|
1564
|
-
cat <<CW_PLIST
|
|
1565
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1566
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1567
|
-
<plist version="1.0">
|
|
1568
|
-
<dict>
|
|
1569
|
-
<key>Label</key>
|
|
1570
|
-
<string>${cw_label}</string>
|
|
1571
|
-
<key>ProgramArguments</key>
|
|
1572
|
-
<array>
|
|
1573
|
-
<string>/bin/bash</string>
|
|
1574
|
-
<string>${_xml_cw_script}</string>
|
|
1575
|
-
<string>scan</string>
|
|
1576
|
-
</array>
|
|
1577
|
-
<key>StartInterval</key>
|
|
1578
|
-
<integer>3600</integer>
|
|
1579
|
-
<key>StandardOutPath</key>
|
|
1580
|
-
<string>${_xml_cw_log_dir}/contribution-watch.log</string>
|
|
1581
|
-
<key>StandardErrorPath</key>
|
|
1582
|
-
<string>${_xml_cw_log_dir}/contribution-watch.log</string>
|
|
1583
|
-
<key>EnvironmentVariables</key>
|
|
1584
|
-
<dict>
|
|
1585
|
-
<key>PATH</key>
|
|
1586
|
-
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
1587
|
-
<key>HOME</key>
|
|
1588
|
-
<string>${_xml_cw_home}</string>
|
|
1589
|
-
</dict>
|
|
1590
|
-
<key>RunAtLoad</key>
|
|
1591
|
-
<false/>
|
|
1592
|
-
<key>KeepAlive</key>
|
|
1593
|
-
<false/>
|
|
1594
|
-
<key>ProcessType</key>
|
|
1595
|
-
<string>Background</string>
|
|
1596
|
-
<key>LowPriorityBackgroundIO</key>
|
|
1597
|
-
<true/>
|
|
1598
|
-
<key>Nice</key>
|
|
1599
|
-
<integer>10</integer>
|
|
1600
|
-
</dict>
|
|
1601
|
-
</plist>
|
|
1602
|
-
CW_PLIST
|
|
1603
|
-
)
|
|
1604
|
-
|
|
1605
|
-
if _launchd_install_if_changed "$cw_label" "$cw_plist" "$cw_plist_content"; then
|
|
1606
|
-
print_info "Contribution watch enabled (launchd, hourly scan)"
|
|
1607
|
-
else
|
|
1608
|
-
print_warning "Failed to load contribution watch LaunchAgent"
|
|
1609
|
-
fi
|
|
1610
|
-
else
|
|
1611
|
-
# Linux: cron entry (hourly)
|
|
1612
|
-
local _cron_cw_script
|
|
1613
|
-
_cron_cw_script=$(_cron_escape "$cw_script")
|
|
1614
|
-
(
|
|
1615
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: contribution-watch'
|
|
1616
|
-
echo "0 * * * * /bin/bash ${_cron_cw_script} scan >> \"${_cw_log_dir}/contribution-watch.log\" 2>&1 # aidevops: contribution-watch"
|
|
1617
|
-
) | crontab - 2>/dev/null || true
|
|
1618
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: contribution-watch" 2>/dev/null; then
|
|
1619
|
-
print_info "Contribution watch enabled (cron, hourly scan)"
|
|
1620
|
-
else
|
|
1621
|
-
print_warning "Failed to install contribution watch cron entry"
|
|
1622
|
-
fi
|
|
1623
|
-
fi
|
|
1624
|
-
fi
|
|
1625
|
-
|
|
1626
|
-
# Draft responses — private repo + local draft storage for reviewing AI-drafted
|
|
1627
|
-
# replies to external contributions (t1555). Creates private draft-responses
|
|
1628
|
-
# repo for GitHub notification-driven approval flow.
|
|
1629
|
-
# Respects config: aidevops config set orchestration.draft_responses false
|
|
1630
|
-
local dr_script="$HOME/.aidevops/agents/scripts/draft-response-helper.sh"
|
|
1631
|
-
if [[ -x "$dr_script" ]] && is_feature_enabled draft_responses 2>/dev/null && is_feature_enabled contribution_watch 2>/dev/null && command -v gh &>/dev/null && gh auth status &>/dev/null 2>&1; then
|
|
1632
|
-
mkdir -p "$HOME/.aidevops/.agent-workspace/draft-responses"
|
|
1633
|
-
if bash "$dr_script" init >/dev/null 2>&1; then
|
|
1634
|
-
print_info "Draft responses ready (private repo + local drafts)"
|
|
1635
|
-
else
|
|
1636
|
-
print_warning "Draft responses repo setup failed (non-fatal, local drafts still work)"
|
|
1637
|
-
fi
|
|
1638
|
-
fi
|
|
1639
|
-
|
|
1640
|
-
# Profile README — auto-create repo and seed README if not already set up.
|
|
1641
|
-
# Requires gh CLI authenticated. Creates username/username repo, seeds README
|
|
1642
|
-
# with stat markers, registers in repos.json with priority: "profile".
|
|
1643
|
-
local pr_script="$HOME/.aidevops/agents/scripts/profile-readme-helper.sh"
|
|
1644
|
-
local pr_label="sh.aidevops.profile-readme-update"
|
|
1645
|
-
local repos_json="$HOME/.config/aidevops/repos.json"
|
|
1646
|
-
if [[ -x "$pr_script" ]] && command -v gh &>/dev/null && gh auth status &>/dev/null; then
|
|
1647
|
-
# Initialize profile repo if not already set up.
|
|
1648
|
-
# Always run init — it's idempotent and handles:
|
|
1649
|
-
# - Fresh installs (no profile repo)
|
|
1650
|
-
# - Missing markers (injects them into existing README)
|
|
1651
|
-
# - Diverged history (repo deleted and recreated on GitHub)
|
|
1652
|
-
# - Already-initialized repos (returns early with no changes)
|
|
1653
|
-
print_info "Checking GitHub profile README..."
|
|
1654
|
-
if bash "$pr_script" init; then
|
|
1655
|
-
print_info "Profile README ready."
|
|
1656
|
-
else
|
|
1657
|
-
print_warning "Profile README setup failed (non-fatal, skipping)"
|
|
1658
|
-
fi
|
|
1659
|
-
fi
|
|
1660
|
-
|
|
1661
|
-
# Profile README auto-update scheduled job.
|
|
1662
|
-
# Installed whenever gh CLI is available — the update script self-heals
|
|
1663
|
-
# (discovers/creates the profile repo on first run via _resolve_profile_repo).
|
|
1664
|
-
# macOS: launchd plist (hourly) | Linux: cron (hourly)
|
|
1665
|
-
if [[ -x "$pr_script" ]] && command -v gh &>/dev/null; then
|
|
1666
|
-
mkdir -p "$HOME/.aidevops/.agent-workspace/logs"
|
|
1667
|
-
|
|
1668
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1669
|
-
local pr_plist="$HOME/Library/LaunchAgents/${pr_label}.plist"
|
|
1670
|
-
|
|
1671
|
-
# XML-escape paths for safe plist embedding
|
|
1672
|
-
local _xml_pr_script _xml_pr_home
|
|
1673
|
-
_xml_pr_script=$(_xml_escape "$pr_script")
|
|
1674
|
-
_xml_pr_home=$(_xml_escape "$HOME")
|
|
1675
|
-
|
|
1676
|
-
local pr_plist_content
|
|
1677
|
-
pr_plist_content=$(
|
|
1678
|
-
cat <<PR_PLIST
|
|
1679
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1680
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1681
|
-
<plist version="1.0">
|
|
1682
|
-
<dict>
|
|
1683
|
-
<key>Label</key>
|
|
1684
|
-
<string>${pr_label}</string>
|
|
1685
|
-
<key>ProgramArguments</key>
|
|
1686
|
-
<array>
|
|
1687
|
-
<string>/bin/bash</string>
|
|
1688
|
-
<string>${_xml_pr_script}</string>
|
|
1689
|
-
<string>update</string>
|
|
1690
|
-
</array>
|
|
1691
|
-
<key>StartInterval</key>
|
|
1692
|
-
<integer>3600</integer>
|
|
1693
|
-
<key>StandardOutPath</key>
|
|
1694
|
-
<string>${_xml_pr_home}/.aidevops/.agent-workspace/logs/profile-readme-update.log</string>
|
|
1695
|
-
<key>StandardErrorPath</key>
|
|
1696
|
-
<string>${_xml_pr_home}/.aidevops/.agent-workspace/logs/profile-readme-update.log</string>
|
|
1697
|
-
<key>EnvironmentVariables</key>
|
|
1698
|
-
<dict>
|
|
1699
|
-
<key>PATH</key>
|
|
1700
|
-
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
1701
|
-
<key>HOME</key>
|
|
1702
|
-
<string>${_xml_pr_home}</string>
|
|
1703
|
-
</dict>
|
|
1704
|
-
<key>RunAtLoad</key>
|
|
1705
|
-
<false/>
|
|
1706
|
-
<key>KeepAlive</key>
|
|
1707
|
-
<false/>
|
|
1708
|
-
<key>ProcessType</key>
|
|
1709
|
-
<string>Background</string>
|
|
1710
|
-
<key>LowPriorityBackgroundIO</key>
|
|
1711
|
-
<true/>
|
|
1712
|
-
<key>Nice</key>
|
|
1713
|
-
<integer>10</integer>
|
|
1714
|
-
</dict>
|
|
1715
|
-
</plist>
|
|
1716
|
-
PR_PLIST
|
|
1717
|
-
)
|
|
1718
|
-
|
|
1719
|
-
if _launchd_install_if_changed "$pr_label" "$pr_plist" "$pr_plist_content"; then
|
|
1720
|
-
print_info "Profile README update enabled (launchd, hourly)"
|
|
1721
|
-
else
|
|
1722
|
-
print_warning "Failed to load profile README update LaunchAgent"
|
|
1723
|
-
fi
|
|
1724
|
-
else
|
|
1725
|
-
# Linux: cron entry (hourly)
|
|
1726
|
-
local _cron_pr_script
|
|
1727
|
-
_cron_pr_script=$(_cron_escape "$pr_script")
|
|
1728
|
-
(
|
|
1729
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: profile-readme-update'
|
|
1730
|
-
echo "0 * * * * /bin/bash ${_cron_pr_script} update >> \"\$HOME/.aidevops/.agent-workspace/logs/profile-readme-update.log\" 2>&1 # aidevops: profile-readme-update"
|
|
1731
|
-
) | crontab - 2>/dev/null || true
|
|
1732
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: profile-readme-update" 2>/dev/null; then
|
|
1733
|
-
print_info "Profile README update enabled (cron, hourly)"
|
|
1734
|
-
else
|
|
1735
|
-
print_warning "Failed to install profile README update cron entry"
|
|
1736
|
-
fi
|
|
1737
|
-
fi
|
|
1738
|
-
fi
|
|
1739
|
-
|
|
1740
|
-
# OAuth token refresh scheduled job.
|
|
1741
|
-
# Refreshes expired/expiring tokens every 30 min so sessions never hit
|
|
1742
|
-
# "invalid x-api-key". Also runs at load to catch tokens that expired
|
|
1743
|
-
# while the machine was off.
|
|
1744
|
-
local tr_script="$HOME/.aidevops/agents/scripts/oauth-pool-helper.sh"
|
|
1745
|
-
local tr_label="sh.aidevops.token-refresh"
|
|
1746
|
-
if [[ -x "$tr_script" ]] && [[ -f "$HOME/.aidevops/oauth-pool.json" ]]; then
|
|
1747
|
-
mkdir -p "$HOME/.aidevops/.agent-workspace/logs"
|
|
1748
|
-
|
|
1749
|
-
if [[ "$(uname -s)" == "Darwin" ]]; then
|
|
1750
|
-
local tr_plist="$HOME/Library/LaunchAgents/${tr_label}.plist"
|
|
1751
|
-
|
|
1752
|
-
local _xml_tr_script _xml_tr_home
|
|
1753
|
-
_xml_tr_script=$(_xml_escape "$tr_script")
|
|
1754
|
-
_xml_tr_home=$(_xml_escape "$HOME")
|
|
1755
|
-
|
|
1756
|
-
local tr_plist_content
|
|
1757
|
-
tr_plist_content=$(
|
|
1758
|
-
cat <<TR_PLIST
|
|
1759
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
1760
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
1761
|
-
<plist version="1.0">
|
|
1762
|
-
<dict>
|
|
1763
|
-
<key>Label</key>
|
|
1764
|
-
<string>${tr_label}</string>
|
|
1765
|
-
<key>ProgramArguments</key>
|
|
1766
|
-
<array>
|
|
1767
|
-
<string>/bin/bash</string>
|
|
1768
|
-
<string>-c</string>
|
|
1769
|
-
<string>${_xml_tr_script} refresh anthropic; ${_xml_tr_script} refresh openai</string>
|
|
1770
|
-
</array>
|
|
1771
|
-
<key>StartInterval</key>
|
|
1772
|
-
<integer>1800</integer>
|
|
1773
|
-
<key>StandardOutPath</key>
|
|
1774
|
-
<string>${_xml_tr_home}/.aidevops/.agent-workspace/logs/token-refresh.log</string>
|
|
1775
|
-
<key>StandardErrorPath</key>
|
|
1776
|
-
<string>${_xml_tr_home}/.aidevops/.agent-workspace/logs/token-refresh.log</string>
|
|
1777
|
-
<key>EnvironmentVariables</key>
|
|
1778
|
-
<dict>
|
|
1779
|
-
<key>PATH</key>
|
|
1780
|
-
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
|
|
1781
|
-
<key>HOME</key>
|
|
1782
|
-
<string>${_xml_tr_home}</string>
|
|
1783
|
-
</dict>
|
|
1784
|
-
<key>RunAtLoad</key>
|
|
1785
|
-
<true/>
|
|
1786
|
-
<key>KeepAlive</key>
|
|
1787
|
-
<false/>
|
|
1788
|
-
<key>ProcessType</key>
|
|
1789
|
-
<string>Background</string>
|
|
1790
|
-
<key>LowPriorityBackgroundIO</key>
|
|
1791
|
-
<true/>
|
|
1792
|
-
<key>Nice</key>
|
|
1793
|
-
<integer>10</integer>
|
|
1794
|
-
</dict>
|
|
1795
|
-
</plist>
|
|
1796
|
-
TR_PLIST
|
|
1797
|
-
)
|
|
1798
|
-
|
|
1799
|
-
if _launchd_install_if_changed "$tr_label" "$tr_plist" "$tr_plist_content"; then
|
|
1800
|
-
print_info "OAuth token refresh enabled (launchd, every 30 min)"
|
|
1801
|
-
else
|
|
1802
|
-
print_warning "Failed to load token refresh LaunchAgent"
|
|
1803
|
-
fi
|
|
1804
|
-
else
|
|
1805
|
-
# Linux: cron entry (every 30 min)
|
|
1806
|
-
local _cron_tr_script
|
|
1807
|
-
_cron_tr_script=$(_cron_escape "$tr_script")
|
|
1808
|
-
(
|
|
1809
|
-
crontab -l 2>/dev/null | grep -v 'aidevops: token-refresh'
|
|
1810
|
-
echo "*/30 * * * * /bin/bash ${_cron_tr_script} refresh anthropic >> \"\$HOME/.aidevops/.agent-workspace/logs/token-refresh.log\" 2>&1; /bin/bash ${_cron_tr_script} refresh openai >> \"\$HOME/.aidevops/.agent-workspace/logs/token-refresh.log\" 2>&1 # aidevops: token-refresh"
|
|
1811
|
-
) | crontab - 2>/dev/null || true
|
|
1812
|
-
if crontab -l 2>/dev/null | grep -qF "aidevops: token-refresh" 2>/dev/null; then
|
|
1813
|
-
print_info "OAuth token refresh enabled (cron, every 30 min)"
|
|
1814
|
-
else
|
|
1815
|
-
print_warning "Failed to install token refresh cron entry"
|
|
1816
|
-
fi
|
|
1817
|
-
fi
|
|
1818
|
-
fi
|
|
1819
|
-
|
|
1820
|
-
echo ""
|
|
1821
|
-
echo "CLI Command:"
|
|
1822
|
-
echo " aidevops init - Initialize aidevops in a project"
|
|
1823
|
-
echo " aidevops features - List available features"
|
|
1824
|
-
echo " aidevops status - Check installation status"
|
|
1825
|
-
echo " aidevops update - Update to latest version"
|
|
1826
|
-
echo " aidevops update-tools - Check for and update installed tools"
|
|
1827
|
-
echo " aidevops uninstall - Remove aidevops"
|
|
1828
|
-
echo ""
|
|
1829
|
-
echo "Deployed to:"
|
|
1830
|
-
echo " ~/.aidevops/agents/ - Agent files (main agents, subagents, scripts)"
|
|
1831
|
-
echo " ~/.aidevops/*-backups/ - Backups with rotation (keeps last $BACKUP_KEEP_COUNT)"
|
|
1832
|
-
echo ""
|
|
1833
|
-
echo "Next steps:"
|
|
1834
|
-
echo "1. Edit configuration files in configs/ with your actual credentials"
|
|
1835
|
-
echo "2. Setup Git CLI tools and authentication (shown during setup)"
|
|
1836
|
-
echo "3. Setup API keys: bash .agents/scripts/setup-local-api-keys.sh setup"
|
|
1837
|
-
echo "4. Test access: ./.agents/scripts/servers-helper.sh list"
|
|
1838
|
-
echo "5. Enable orchestration: see runners.md 'Pulse Scheduler Setup' (autonomous task dispatch)"
|
|
1839
|
-
echo "6. Read documentation: ~/.aidevops/agents/AGENTS.md"
|
|
1840
|
-
echo ""
|
|
1841
|
-
echo "For development on aidevops framework itself:"
|
|
1842
|
-
echo " See ~/Git/aidevops/AGENTS.md"
|
|
1843
|
-
echo ""
|
|
1844
|
-
echo "OpenCode Primary Agents (12 total, Tab to switch):"
|
|
1845
|
-
echo "• Plan+ - Enhanced planning with context tools (read-only)"
|
|
1846
|
-
echo "• Build+ - Enhanced build with context tools (full access)"
|
|
1847
|
-
echo "• Accounts, AI-DevOps, Content, Health, Legal, Marketing,"
|
|
1848
|
-
echo " Research, Sales, SEO, WordPress"
|
|
1849
|
-
echo ""
|
|
1850
|
-
echo "Agent Skills (SKILL.md):"
|
|
1851
|
-
echo "• 21 SKILL.md files generated in ~/.aidevops/agents/"
|
|
1852
|
-
echo "• Skills include: wordpress, seo, aidevops, build-mcp, and more"
|
|
1853
|
-
echo ""
|
|
1854
|
-
echo "MCP Integrations (OpenCode):"
|
|
1855
|
-
echo "• Augment Context Engine - Cloud semantic codebase retrieval"
|
|
1856
|
-
echo "• Context7 - Real-time library documentation"
|
|
1857
|
-
echo "• GSC - Google Search Console (MCP + OAuth2)"
|
|
1858
|
-
echo "• Google Analytics - Analytics data (shared GSC credentials)"
|
|
1859
|
-
echo ""
|
|
1860
|
-
echo "SEO Integrations (curl subagents - no MCP overhead):"
|
|
1861
|
-
echo "• DataForSEO - Comprehensive SEO data APIs"
|
|
1862
|
-
echo "• Serper - Google Search API"
|
|
1863
|
-
echo "• Ahrefs - Backlink and keyword data"
|
|
1864
|
-
echo ""
|
|
1865
|
-
echo "DSPy & DSPyGround Integration:"
|
|
1866
|
-
echo "• ./.agents/scripts/dspy-helper.sh - DSPy prompt optimization toolkit"
|
|
1867
|
-
echo "• ./.agents/scripts/dspyground-helper.sh - DSPyGround playground interface"
|
|
1868
|
-
echo "• python-env/dspy-env/ - Python virtual environment for DSPy"
|
|
1869
|
-
echo "• data/dspy/ - DSPy projects and datasets"
|
|
1870
|
-
echo "• data/dspyground/ - DSPyGround projects and configurations"
|
|
1871
|
-
echo ""
|
|
1872
|
-
echo "Task Management:"
|
|
1873
|
-
echo "• Beads CLI (bd) - Task graph visualization"
|
|
1874
|
-
echo "• beads-sync-helper.sh - Sync TODO.md/PLANS.md with Beads"
|
|
1875
|
-
echo "• todo-ready.sh - Show tasks with no open blockers"
|
|
1876
|
-
echo "• Run: aidevops init beads - Initialize Beads in a project"
|
|
1877
|
-
echo ""
|
|
1878
|
-
echo "Autonomous Orchestration:"
|
|
1879
|
-
echo "• Supervisor pulse - Dispatches workers, merges PRs, evaluates results"
|
|
1880
|
-
echo "• Auto-pickup - Workers claim #auto-dispatch tasks from TODO.md"
|
|
1881
|
-
echo "• Cross-repo visibility - Manages tasks across all repos in repos.json"
|
|
1882
|
-
echo "• Strategic review (opus) - 4-hourly queue health, root cause analysis"
|
|
1883
|
-
echo "• Model routing - Cost-aware: local>haiku>flash>sonnet>pro>opus"
|
|
1884
|
-
echo "• Budget tracking - Per-provider spend limits, subscription-aware"
|
|
1885
|
-
echo "• Session miner - Extracts learning from past sessions"
|
|
1886
|
-
echo "• Circuit breaker - Pauses dispatch on consecutive failures"
|
|
1887
|
-
echo ""
|
|
1888
|
-
echo " Supervisor pulse (autonomous orchestration) requires explicit consent."
|
|
1889
|
-
echo " Enable: aidevops config set orchestration.supervisor_pulse true && ./setup.sh"
|
|
1890
|
-
echo ""
|
|
1891
|
-
echo " Run /onboarding in your AI assistant to configure services interactively."
|
|
1892
|
-
echo ""
|
|
1893
|
-
echo "Security reminders:"
|
|
1894
|
-
echo "- Never commit configuration files with real credentials"
|
|
1895
|
-
echo "- Use strong passwords and enable MFA on all accounts"
|
|
1896
|
-
echo "- Regularly rotate API tokens and SSH keys"
|
|
1897
|
-
echo ""
|
|
1898
|
-
echo "Happy server managing! 🚀"
|
|
1899
|
-
echo ""
|
|
870
|
+
# Post-setup: auto-update, schedulers, final instructions (GH#5793)
|
|
871
|
+
setup_auto_update
|
|
872
|
+
setup_supervisor_pulse "$_os"
|
|
873
|
+
setup_stats_wrapper "${PULSE_ENABLED:-}"
|
|
874
|
+
setup_repo_sync
|
|
875
|
+
setup_process_guard
|
|
876
|
+
setup_memory_pressure_monitor
|
|
877
|
+
setup_screen_time_snapshot
|
|
878
|
+
setup_contribution_watch
|
|
879
|
+
setup_draft_responses
|
|
880
|
+
setup_profile_readme
|
|
881
|
+
setup_oauth_token_refresh
|
|
882
|
+
print_final_instructions
|
|
1900
883
|
|
|
1901
884
|
# Check for tool updates if --update flag was passed
|
|
1902
885
|
if [[ "$UPDATE_TOOLS_MODE" == "true" ]]; then
|
|
@@ -1904,32 +887,7 @@ TR_PLIST
|
|
|
1904
887
|
check_tool_updates
|
|
1905
888
|
fi
|
|
1906
889
|
|
|
1907
|
-
|
|
1908
|
-
# Respects config: aidevops config set ui.onboarding_prompt false
|
|
1909
|
-
if [[ "$NON_INTERACTIVE" != "true" ]] && [[ -z "${OPENCODE_SESSION:-}" ]] && is_feature_enabled onboarding_prompt 2>/dev/null && command -v opencode &>/dev/null; then
|
|
1910
|
-
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
1911
|
-
echo ""
|
|
1912
|
-
echo "Ready to configure your services?"
|
|
1913
|
-
echo ""
|
|
1914
|
-
echo "Launch OpenCode with the onboarding wizard to:"
|
|
1915
|
-
echo " - See which services are already configured"
|
|
1916
|
-
echo " - Get personalized recommendations based on your work"
|
|
1917
|
-
echo " - Set up API keys and credentials interactively"
|
|
1918
|
-
echo ""
|
|
1919
|
-
read -r -p "Launch OpenCode with /onboarding now? [Y/n]: " launch_onboarding
|
|
1920
|
-
if [[ "$launch_onboarding" =~ ^[Yy]?$ || "$launch_onboarding" == "Y" ]]; then
|
|
1921
|
-
echo ""
|
|
1922
|
-
echo "Starting OpenCode with onboarding wizard..."
|
|
1923
|
-
# Launch with /onboarding prompt only — don't use --agent flag because
|
|
1924
|
-
# the "Onboarding" agent only exists after generate-opencode-agents.sh
|
|
1925
|
-
# writes to opencode.json, which requires opencode.json to already exist.
|
|
1926
|
-
# On first run it won't, so --agent "Onboarding" causes a fatal error.
|
|
1927
|
-
opencode --prompt "/onboarding"
|
|
1928
|
-
else
|
|
1929
|
-
echo ""
|
|
1930
|
-
echo "You can run /onboarding anytime in OpenCode to configure services."
|
|
1931
|
-
fi
|
|
1932
|
-
fi
|
|
890
|
+
setup_onboarding_prompt
|
|
1933
891
|
|
|
1934
892
|
return 0
|
|
1935
893
|
}
|