-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain-cli.sh
More file actions
executable file
·445 lines (394 loc) · 16.1 KB
/
Copy pathmain-cli.sh
File metadata and controls
executable file
·445 lines (394 loc) · 16.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
SCRIPTS_DIR="$ROOT_DIR/scripts"
LOG_FILE="$ROOT_DIR/server.log"
if ! command -v gum >/dev/null 2>&1; then
echo "The Gum CLI is required for this script." >&2
echo "Install instructions: https://github.com/charmbracelet/gum#installation" >&2
exit 1
fi
if [ ! -d "$SCRIPTS_DIR" ]; then
echo "scripts/ directory not found. Please ensure helper scripts exist." >&2
exit 1
fi
print_header() {
gum style \
--border double \
--padding "1 2" \
--margin "1 0" \
--border-foreground 212 \
"AI Agent Messaging Platform" \
"Main Control Menu"
}
command_preview() {
local title="$1"
local detail="$2"
shift 2
local -a cmd=("$@")
local preview=""
for part in "${cmd[@]}"; do
preview+="$(printf '%q ' "$part")"
done
gum style --margin "1 0" --bold "$title"
gum style --foreground 250 "$detail"
gum style --foreground 36 "Command preview:"
gum style --foreground 244 "$preview"
if gum confirm --affirmative "Run" --negative "Cancel" "Execute this command?"; then
"${cmd[@]}"
else
gum style --foreground 214 "Action cancelled"
fi
}
action_initial_setup() {
gum style --foreground 212 "Environment setup"
gum style --foreground 244 "Choose whether to bootstrap the database schema."
local run_db="false"
if gum confirm --affirmative "Bootstrap" --negative "Skip" "Run database setup after npm install?"; then
run_db="true"
fi
command_preview \
"Initial setup" \
"Prepare .env, install dependencies, and optionally run the DB setup script." \
env "RUN_DB_SETUP=$run_db" "$SCRIPTS_DIR/initial_setup.sh"
}
action_setup_env_template() {
command_preview \
"Setup .env from template" \
"Copy local/staging/production template into .env (overwrite prompt included)." \
"$SCRIPTS_DIR/setup_env_from_template.sh"
}
action_configure_email() {
gum style --foreground 212 "Email configuration"
gum style --foreground 244 "Modify SMTP host, credentials, and sender/reply-to values."
gum style --foreground 244 "You'll be prompted to send a test email with the configured settings."
command_preview \
"Configure email settings" \
"Prompt for all EMAIL_* variables so the app can send mail." \
"$SCRIPTS_DIR/configure_email.sh"
}
action_check_prereqs() {
command_preview \
"Check prerequisites" \
"Verify Node, npm, and PostgreSQL command-line tools are available." \
"$SCRIPTS_DIR/check_prereqs.sh"
}
action_run_db_setup() {
gum style --foreground 214 "This will run the PostgreSQL bootstrap (uses sudo)."
gum style --foreground "9" --bold "WARNING: This will DELETE ALL existing data in the database."
if ! gum confirm --affirmative "Proceed and delete data" --negative "Cancel" "Do you want to continue?"; then
gum style --foreground 214 "Action cancelled."
return
fi
command_preview \
"Database setup" \
"Provision the PostgreSQL database and apply schema migrations." \
"$SCRIPTS_DIR/run_db_setup.sh"
}
action_fix_db() {
command_preview \
"Fix database authentication" \
"Diagnose and repair database connection issues." \
"$SCRIPTS_DIR/fix_db_auth.sh"
}
action_fix_db_owner() {
command_preview \
"Fix database ownership" \
"Repair table/sequence ownership so migrations can alter schema." \
"$SCRIPTS_DIR/fix_db_ownership.sh"
}
action_restart_db() {
command_preview \
"Restart database" \
"Restart the PostgreSQL service without losing data." \
"sudo" "service" "postgresql" "restart"
}
action_start_server() {
command_preview \
"Start server" \
"Launch npm start in the background and capture logs to server.log." \
"$SCRIPTS_DIR/start_server.sh"
}
action_start_app_foreground() {
command_preview \
"Start server (foreground)" \
"Ensure environment/dependencies, then run npm start in the foreground." \
"$SCRIPTS_DIR/start_app.sh"
}
action_start_production() {
command_preview \
"Start server (production)" \
"Prep env/deps, verify DB, then start with NODE_ENV=production in the foreground." \
"$SCRIPTS_DIR/start_production.sh"
}
action_start_production_supervised() {
gum style --foreground 212 "Supervised production (auto-restart + persistent)"
gum style --foreground 244 "Installs a systemd service that starts on boot and restarts on crashes."
gum style --foreground 244 "Limits restart storms to 5 crashes per 10 minutes; writes crash alerts to server_crash.log."
command_preview \
"Start server (production, supervised)" \
"Install/enable a persistent systemd service that auto-restarts on crashes and appends logs to server.log." \
"$SCRIPTS_DIR/start_production_supervised.sh"
}
action_start_dev_mode() {
gum style --foreground "9" --bold "⚠️ SECURITY WARNING ⚠️"
gum style --foreground "9" "This mode creates a default user with INSECURE credentials!"
gum style --foreground "9" " Email: 123@gmail.com"
gum style --foreground "9" " Password: 12345678"
echo ""
gum style --foreground "214" "This is for LOCAL DEVELOPMENT/TESTING ONLY."
gum style --foreground "214" "DO NOT use in production or expose to the internet!"
echo ""
command_preview \
"Start server (dev mode)" \
"Create default test user and start server for local testing without authentication setup." \
"$SCRIPTS_DIR/start_dev_mode.sh"
}
action_setup_nginx() {
gum style --foreground 212 "Configure Nginx reverse proxy on port 80 (requires sudo)."
gum style --foreground 244 "This will install nginx if missing, write /etc/nginx/sites-available/agent-messaging-platform.conf, and reload nginx."
command_preview \
"Setup Nginx reverse proxy" \
"Proxy :80 to the app's PORT (defaults to 3000 if PORT is privileged)." \
"$SCRIPTS_DIR/setup_nginx_reverse_proxy.sh"
}
action_start_redis() {
command_preview \
"Start Redis (local)" \
"Launch a local redis-server if not running and ensure .env has Redis defaults." \
"$SCRIPTS_DIR/start_redis.sh"
}
action_launch_agent() {
gum style --foreground 212 "One-Shot Agent Launcher"
gum style --foreground 244 "Configure and start the AI agent with interactive prompts."
gum style --foreground 244 "The agent will run in one-shot mode, processing messages and exiting."
if gum confirm --affirmative "Launch" --negative "Cancel" "Open the agent launcher?"; then
if [ -x "$ROOT_DIR/.chatspace/cli-test-agent/agent-launcher.sh" ]; then
exec "$ROOT_DIR/.chatspace/cli-test-agent/agent-launcher.sh"
fi
exec "$ROOT_DIR/chatspace/cli-test-agent/agent-launcher.sh"
else
gum style --foreground 214 "Action cancelled"
fi
}
action_start_local_stack() {
gum style --foreground 212 "Start local PostgreSQL and Redis (requires sudo for Postgres)."
gum style --foreground 244 "Sets local defaults in .env if missing, then starts services."
command_preview \
"Start local DB + Redis" \
"Ensure .env defaults, start PostgreSQL service, then start Redis." \
"$SCRIPTS_DIR/start_local_stack.sh"
}
action_setup_tls() {
gum style --foreground 212 "Obtain Let's Encrypt cert (standalone) and update .env for in-app TLS."
gum style --foreground 244 "Requires ports 80/443 and sudo for certbot installation."
command_preview \
"Setup TLS (certbot)" \
"Acquire/renew certs and write HTTPS_ settings into .env." \
"$SCRIPTS_DIR/setup_tls_certbot.sh"
}
action_renew_tls() {
gum style --foreground 212 "Renew/reinstall TLS cert, enable auto-renew, and install hardening hook."
gum style --foreground 244 "Uses certbot+nginx, enables certbot.timer, installs nginx reload hook, and runs dry-run renewal."
command_preview \
"Renew TLS + harden certbot" \
"Repair expired certs and configure renewal automation for future rotations." \
"$SCRIPTS_DIR/renew_tls_certbot.sh"
}
action_check_https() {
command_preview \
"Check HTTPS reachability" \
"Prompt for an https:// URL (defaults to BASE_URL if present) and verify it responds with 2xx/3xx." \
"$SCRIPTS_DIR/check_https_site.sh"
}
action_bootstrap_all() {
command_preview \
"Bootstrap machine" \
"Install system deps, prepare .env, install npm deps, set up DB/Redis, and start the server." \
"$SCRIPTS_DIR/bootstrap_machine.sh"
}
action_stop_server() {
command_preview \
"Stop server" \
"Terminate the running server process recorded in tmp/server.pid." \
"$SCRIPTS_DIR/stop_server.sh"
}
action_server_status() {
command_preview \
"Server status" \
"Interactive status dashboard (process, traffic, system, Postgres, Redis)." \
"$SCRIPTS_DIR/server_status.sh"
}
action_server_status_file() {
command_preview \
"Server status file" \
"Write a status snapshot to server_status.txt every 5 minutes (Ctrl+C to stop)." \
"$SCRIPTS_DIR/server_status_file.sh"
}
action_follow_logs() {
local default_lines="200"
local lines
lines=$(gum input --placeholder "Lines to tail" --value "$default_lines" --prompt "Tail lines > ")
if [ -z "$lines" ]; then
lines="$default_lines"
fi
if ! [[ "$lines" =~ ^[0-9]+$ ]]; then
gum style --foreground 9 "Invalid number of lines: $lines"
return
fi
command_preview \
"Follow logs" \
"Stream server.log with tail -f showing the last $lines lines." \
"$SCRIPTS_DIR/follow_logs.sh" "$lines"
}
action_view_log() {
command_preview \
"View full log" \
"Open server.log in your default pager for inspection." \
"$SCRIPTS_DIR/view_log.sh"
}
action_run_tests_suite() {
gum style --foreground 212 "Test suite & UI checklist"
gum style --foreground 244 "Run automated Jest + Python helper tests, then confirm the UI behaves after agent deletion."
if gum confirm --affirmative "Run tests" --negative "Skip" "Execute the automated test suite now?"; then
set +e
(cd "$ROOT_DIR" && "$SCRIPTS_DIR/run_tests.sh")
status=$?
set -e
if [ "$status" -eq 0 ]; then
gum style --foreground 82 "✓ Automated tests passed"
else
gum style --foreground 9 "✗ Automated tests failed (exit $status). Review the log above."
fi
fi
gum style --margin "1 0" --foreground 212 "Manual UI checklist (agent deletion)"
gum style --foreground 244 "Open the web app, delete a test agent, and check each item below:"
local steps=(
"Agent disappears from the Agents list immediately after deletion"
"Other agents still load histories and messages without errors"
"Deleted agent stays gone after refreshing the Agents list"
"No toast/error banners appear after deletion; history for the deleted agent is inaccessible"
)
gum choose --no-limit --cursor "➤ " --selected-prefix "✓ " --unselected-prefix "• " "${steps[@]}" >/dev/null
gum style --foreground 36 "Checklist recorded. Capture screenshots/log snippets for any failed items."
}
action_manage_users() {
command_preview \
"Manage Users" \
"List, search, and delete users (and their data) from the database." \
"$SCRIPTS_DIR/manage_users.sh"
}
action_show_google_auth_walkthrough() {
"$SCRIPTS_DIR/show_google_auth_walkthrough.sh"
}
action_test_cli_providers() {
gum style \
--border double \
--padding "1 2" \
--margin "1 0" \
--border-foreground 212 \
"🧪 CLI Provider Test Suite" \
"Test Codex, Claude, Gemini, and local providers"
echo ""
gum style --foreground 244 "This test suite will:"
gum style --foreground 244 " • Test selected CLI providers with various configurations"
gum style --foreground 244 " • Use a weather query that requires internet access"
gum style --foreground 244 " • Log results to tests/test-results/ directory"
echo ""
# Build test selection and pass to the test script
local test_script="$ROOT_DIR/tests/cli-provider-test.sh"
if [ ! -f "$test_script" ]; then
gum style --foreground 9 "✗ Test script not found: $test_script"
return 1
fi
# Run the test script with its unified menu
"$test_script"
}
show_menu_and_get_selection() {
local entries=()
local menu_items=(
"bootstrap|Bootstrap machine|Install deps, prep env, set up DB/Redis, start server"
"prereqs|Check prerequisites|Ensure Node/npm/PostgreSQL CLIs are present"
"env|Setup .env from template|Copy local/staging/prod template into .env"
"email|Configure email settings|Adjust SMTP host/port/auth and sender addresses"
"google_auth|Google Auth Help|Show verification steps for Google Sign-In"
"users|Manage Users|List and delete users/data"
"agent|Launch AI Agent|Start one-shot agent with interactive configuration"
"tests|Run tests & UI checks|Automated Jest suite plus manual UI checklist"
"cli_tests|Test CLI Providers|🧪 Test Codex, Claude, and Gemini CLI configurations"
"redis|Start Redis (local)|Start redis-server locally and set .env defaults"
"local_stack|Start DB + Redis (local)|Start PostgreSQL and Redis locally; patch .env defaults"
"tls|Setup TLS (Let's Encrypt)|Use certbot standalone to fetch certs and update .env"
"tls_renew|Renew TLS + harden certbot|Repair/renew cert, enable timer, install reload hook, run dry-run checks"
"https_check|Check HTTPS reachability|Verify a site responds over HTTPS"
"setup|Initial setup|Configure .env, install dependencies, bootstrap DB"
"nginx|Setup Nginx reverse proxy|Install/configure Nginx to proxy :80 to app port"
"db|Run database setup|Provision PostgreSQL and apply schema"
"start_fg|Start server (foreground)|Ensure env/deps then run npm start interactively"
"start_dev|Start server (dev mode)|⚠️ INSECURE: Create test user 123@gmail.com for local testing"
"start_prod|Start server (production)|Prep env/deps, verify DB, start with NODE_ENV=production"
"start_prod_supervised|Start server (production, supervised)|Auto-restart on crash + start on boot (systemd, max 5 retries)"
"start|Start server|Run npm start in the background"
"status|Server status|Check PID and log file location"
"status_file|Server status file|Write a server_status.txt snapshot every 5 minutes"
"follow_logs|Follow logs|Stream server.log with tail -f"
"view_log|View full log|Open server.log inside a pager"
"stop|Stop server|Stop the running server process"
"fix_db|Fix database auth|Diagnose and repair database connection issues"
"fix_owner|Fix DB ownership|Repair owner/permissions for migration ALTER statements"
"restart_db|Restart DB service|Restart PostgreSQL without data loss"
"backup|Backup database|Create compressed pg_dump in backups/"
"backup_timer|Install backup timer|Install/enable daily systemd user timer"
"quit|Quit|Exit this menu"
)
for item in "${menu_items[@]}"; do
IFS="|" read -r key title desc <<<"$item"
entries+=("[$key] $title — $desc")
done
print_header
local height="${#entries[@]}"
if [ "$height" -lt 1 ]; then
height=1
fi
gum choose --height "$height" --cursor "➤ " "${entries[@]}"
}
while true; do
selection=$(show_menu_and_get_selection)
key=$(sed -n 's/^\[\([^]]*\)\].*/\1/p' <<<"$selection")
case "$key" in
env) action_setup_env_template ;;
email) action_configure_email ;;
google_auth) action_show_google_auth_walkthrough ;;
users) action_manage_users ;;
prereqs) action_check_prereqs ;;
agent) action_launch_agent ;;
setup) action_initial_setup ;;
nginx) action_setup_nginx ;;
tls) action_setup_tls ;;
tls_renew) action_renew_tls ;;
https_check) action_check_https ;;
local_stack) action_start_local_stack ;;
db) action_run_db_setup ;;
start_prod) action_start_production ;;
start_prod_supervised) action_start_production_supervised ;;
fix_db) action_fix_db ;;
fix_owner) action_fix_db_owner ;;
restart_db) action_restart_db ;;
backup) "$SCRIPTS_DIR/backup_db.sh" ;;
backup_timer) "$SCRIPTS_DIR/install_backup_timer.sh" ;;
redis) action_start_redis ;;
bootstrap) action_bootstrap_all ;;
start) action_start_server ;;
start_fg) action_start_app_foreground ;;
start_dev) action_start_dev_mode ;;
tests) action_run_tests_suite ;;
cli_tests) action_test_cli_providers ;;
stop) action_stop_server ;;
status) action_server_status ;;
status_file) action_server_status_file ;;
follow_logs) action_follow_logs ;;
view_log) action_view_log ;;
quit) exit 0 ;;
*) gum style --foreground 9 "Unknown action: $key" ;;
esac
done