wait for instance to be ready and return to manage screen

This commit is contained in:
Nicolas Leão 2026-03-03 16:19:07 -03:00
parent 7103367640
commit 3be36993c3
2 changed files with 336 additions and 300 deletions

View file

@ -327,6 +327,34 @@ function Get-NonEmptyLines {
return @($lines | ForEach-Object { "$($_)".Trim() } | Where-Object { -not [string]::IsNullOrWhiteSpace($_) })
}
function Wait-ForReady {
param([string]$Url)
$maxWait = 60
$waited = 0
Write-Host "[INFO] Launching Agent Zero..." -ForegroundColor Green -NoNewline
while ($waited -lt $maxWait) {
try {
$response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 2 -ErrorAction Stop
if ($response.StatusCode -ge 200 -and $response.StatusCode -lt 400) {
Write-Host ''
print_ok "Agent Zero is ready at $Url"
return $true
}
}
catch { }
Start-Sleep -Seconds 1
$waited++
Write-Host '.' -NoNewline
}
Write-Host ''
print_warn "Agent Zero did not respond within $maxWait seconds. It may still be starting up."
return $false
}
# Uses image name string matching instead of ancestor filter.
# The ancestor filter matches by image ID, not name, so containers created
# from a previous version of a tag become invisible after pulling a newer version.
@ -652,32 +680,11 @@ function create_instance {
throw 'Failed to start Agent Zero.'
}
Write-Host ''
Write-Host '=========================================='
Write-Host ' Installation Complete!' -ForegroundColor Green
Write-Host '=========================================='
Write-Host ''
Write-Host " Image tag : $script:SelectedTag"
Write-Host " Instance name : $containerName"
Write-Host " Compose file : $composeFile"
Write-Host " Data directory : $dataDir"
Write-Host " Web UI : http://localhost:$port"
if (-not [string]::IsNullOrWhiteSpace($authLogin)) {
Write-Host ' Authentication : enabled'
Write-Host " Login : $authLogin"
Write-Host " Password : $authPassword"
}
else {
Write-Host ' Authentication : none'
}
Write-Host ''
Write-Host ' Useful commands:'
Write-Host " docker compose -f `"$composeFile`" logs -f # View logs"
Write-Host " docker compose -f `"$composeFile`" down # Stop"
Write-Host " docker compose -f `"$composeFile`" up -d # Start"
Write-Host " docker compose -f `"$composeFile`" pull # Update image"
Write-Host ''
print_info 'Happy automating with Agent Zero!'
# Wait for the service to become ready
Wait-ForReady -Url "http://localhost:$port"
# Store the created container name for the caller
$script:CreatedContainerName = $containerName
return $true
}
@ -742,140 +749,149 @@ function manage_instances {
$selectedRow = $containerRows[$selectedIndex]
$selectedParts = $selectedRow -split '\|', 3
$selectedName = if ($selectedParts.Count -ge 1) { $selectedParts[0] } else { '' }
$selectedImage = if ($selectedParts.Count -ge 2) { $selectedParts[1] } else { '' }
# Inner action loop for the selected container
while ($true) {
$statusOutput = & docker ps -a --filter "name=^/$selectedName$" --format '{{.Status}}' 2>$null
$selectedStatus = ((Get-NonEmptyLines $statusOutput) | Select-Object -First 1)
manage_single_instance -ContainerName $selectedName
}
}
# If container no longer exists (e.g. after delete), go back to instance list
if ([string]::IsNullOrWhiteSpace($selectedStatus)) {
# Show the action menu for a single container (open, start, stop, restart, delete).
# Can be called from manage_instances or directly after create_instance.
function manage_single_instance {
param([string]$ContainerName)
# Look up the image for display
$selectedImage = ((Get-NonEmptyLines (& docker ps -a --filter "name=^/$ContainerName$" --format '{{.Image}}' 2>$null)) | Select-Object -First 1)
while ($true) {
$statusOutput = & docker ps -a --filter "name=^/$ContainerName$" --format '{{.Status}}' 2>$null
$selectedStatus = ((Get-NonEmptyLines $statusOutput) | Select-Object -First 1)
# If container no longer exists (e.g. after delete), return
if ([string]::IsNullOrWhiteSpace($selectedStatus)) {
break
}
$isRunning = $selectedStatus -like 'Up*'
$instanceHeader = "Selected: $ContainerName ($selectedImage, $selectedStatus)"
if ($isRunning) {
$actionOptions = @('Open in browser', 'Restart', 'Stop', 'Delete', 'Back')
$actionIndex = select_from_menu -Header $instanceHeader -Options $actionOptions
switch ($actionIndex) {
-1 { $actionKey = 'back' } # Escape/Backspace
0 { $actionKey = 'open' }
1 { $actionKey = 'restart' }
2 { $actionKey = 'stop' }
3 { $actionKey = 'delete' }
4 { $actionKey = 'back' }
default { $actionKey = 'invalid' }
}
}
else {
$actionOptions = @('Start', 'Delete', 'Back')
$actionIndex = select_from_menu -Header $instanceHeader -Options $actionOptions
switch ($actionIndex) {
-1 { $actionKey = 'back' } # Escape/Backspace
0 { $actionKey = 'start' }
1 { $actionKey = 'delete' }
2 { $actionKey = 'back' }
default { $actionKey = 'invalid' }
}
}
switch ($actionKey) {
'open' {
$portOutput = & docker port $ContainerName '80/tcp' 2>$null
$hostPort = ''
foreach ($line in (Get-NonEmptyLines $portOutput)) {
if ($line -match ':(\d+)\s*$') {
$hostPort = $Matches[1]
break
}
}
if ([string]::IsNullOrWhiteSpace($hostPort)) {
print_warn "Could not resolve a host port for '$ContainerName' on 80/tcp. Ensure it is running with a published port."
}
else {
$targetUrl = "http://localhost:$hostPort"
print_info "Opening $targetUrl"
open_browser -Url $targetUrl
}
Wait-ForKeypress
}
'start' {
print_info "Starting '$ContainerName'..."
$startOutput = & docker start $ContainerName 2>&1
# Verify actual container state
$runCheck = & docker ps --filter "name=^/$ContainerName$" --filter 'status=running' --format '{{.Names}}' 2>$null
if ((Get-NonEmptyLines $runCheck) -contains $ContainerName) {
print_ok "Started '$ContainerName'."
}
else {
print_error "Failed to start '$ContainerName'."
if ($startOutput) {
Write-Host " $startOutput"
}
}
Wait-ForKeypress
}
'stop' {
print_info "Stopping '$ContainerName'..."
& docker stop $ContainerName *> $null
if ($LASTEXITCODE -eq 0) {
print_ok "Stopped '$ContainerName'."
}
else {
print_error "Failed to stop '$ContainerName'."
}
Wait-ForKeypress
}
'restart' {
print_info "Restarting '$ContainerName'..."
$restartOutput = & docker restart $ContainerName 2>&1
# Verify actual container state
$runCheck = & docker ps --filter "name=^/$ContainerName$" --filter 'status=running' --format '{{.Names}}' 2>$null
if ((Get-NonEmptyLines $runCheck) -contains $ContainerName) {
print_ok "Restarted '$ContainerName'."
}
else {
print_error "Failed to restart '$ContainerName'."
if ($restartOutput) {
Write-Host " $restartOutput"
}
}
Wait-ForKeypress
}
'delete' {
Write-Host "Are you sure you want to delete '$ContainerName'? [y/N]: " -NoNewline
$confirmKey = [Console]::ReadKey($true)
Write-Host ''
if ($confirmKey.KeyChar -eq 'y' -or $confirmKey.KeyChar -eq 'Y') {
# Stop first if running
& docker stop $ContainerName *> $null
& docker rm $ContainerName *> $null
if ($LASTEXITCODE -eq 0) {
print_ok "Deleted '$ContainerName'."
}
else {
print_error "Failed to delete '$ContainerName'."
}
Wait-ForKeypress
break # Container no longer exists
}
else {
print_info 'Delete cancelled.'
Wait-ForKeypress
}
}
'back' {
break
}
$isRunning = $selectedStatus -like 'Up*'
$instanceHeader = "Selected: $selectedName ($selectedImage, $selectedStatus)"
if ($isRunning) {
$actionOptions = @('Open in browser', 'Restart', 'Stop', 'Delete', 'Back')
$actionIndex = select_from_menu -Header $instanceHeader -Options $actionOptions
switch ($actionIndex) {
-1 { $actionKey = 'back' } # Escape/Backspace
0 { $actionKey = 'open' }
1 { $actionKey = 'restart' }
2 { $actionKey = 'stop' }
3 { $actionKey = 'delete' }
4 { $actionKey = 'back' }
default { $actionKey = 'invalid' }
}
}
else {
$actionOptions = @('Start', 'Delete', 'Back')
$actionIndex = select_from_menu -Header $instanceHeader -Options $actionOptions
switch ($actionIndex) {
-1 { $actionKey = 'back' } # Escape/Backspace
0 { $actionKey = 'start' }
1 { $actionKey = 'delete' }
2 { $actionKey = 'back' }
default { $actionKey = 'invalid' }
}
}
switch ($actionKey) {
'open' {
$portOutput = & docker port $selectedName '80/tcp' 2>$null
$hostPort = ''
foreach ($line in (Get-NonEmptyLines $portOutput)) {
if ($line -match ':(\d+)\s*$') {
$hostPort = $Matches[1]
break
}
}
if ([string]::IsNullOrWhiteSpace($hostPort)) {
print_warn "Could not resolve a host port for '$selectedName' on 80/tcp. Ensure it is running with a published port."
}
else {
$targetUrl = "http://localhost:$hostPort"
print_info "Opening $targetUrl"
open_browser -Url $targetUrl
}
Wait-ForKeypress
}
'start' {
print_info "Starting '$selectedName'..."
$startOutput = & docker start $selectedName 2>&1
# Verify actual container state
$runCheck = & docker ps --filter "name=^/$selectedName$" --filter 'status=running' --format '{{.Names}}' 2>$null
if ((Get-NonEmptyLines $runCheck) -contains $selectedName) {
print_ok "Started '$selectedName'."
}
else {
print_error "Failed to start '$selectedName'."
if ($startOutput) {
Write-Host " $startOutput"
}
}
Wait-ForKeypress
}
'stop' {
print_info "Stopping '$selectedName'..."
& docker stop $selectedName *> $null
if ($LASTEXITCODE -eq 0) {
print_ok "Stopped '$selectedName'."
}
else {
print_error "Failed to stop '$selectedName'."
}
Wait-ForKeypress
}
'restart' {
print_info "Restarting '$selectedName'..."
$restartOutput = & docker restart $selectedName 2>&1
# Verify actual container state
$runCheck = & docker ps --filter "name=^/$selectedName$" --filter 'status=running' --format '{{.Names}}' 2>$null
if ((Get-NonEmptyLines $runCheck) -contains $selectedName) {
print_ok "Restarted '$selectedName'."
}
else {
print_error "Failed to restart '$selectedName'."
if ($restartOutput) {
Write-Host " $restartOutput"
}
}
Wait-ForKeypress
}
'delete' {
Write-Host "Are you sure you want to delete '$selectedName'? [y/N]: " -NoNewline
$confirmKey = [Console]::ReadKey($true)
Write-Host ''
if ($confirmKey.KeyChar -eq 'y' -or $confirmKey.KeyChar -eq 'Y') {
# Stop first if running
& docker stop $selectedName *> $null
& docker rm $selectedName *> $null
if ($LASTEXITCODE -eq 0) {
print_ok "Deleted '$selectedName'."
}
else {
print_error "Failed to delete '$selectedName'."
}
Wait-ForKeypress
break # Back to instance list (container no longer exists)
}
else {
print_info 'Delete cancelled.'
Wait-ForKeypress
}
}
'back' {
break # Break inner loop, go back to instance selection
}
default {
print_warn 'Invalid action. Please try again.'
Wait-ForKeypress
}
default {
print_warn 'Invalid action. Please try again.'
Wait-ForKeypress
}
}
}
@ -894,11 +910,12 @@ function main_menu_for_existing {
switch ($selectedIndex) {
-1 { exit 0 } # Escape/Backspace - exit
0 {
$script:CreatedContainerName = ''
$result = create_instance
if ($result) {
return # Install completed successfully
manage_single_instance -ContainerName $script:CreatedContainerName
}
# Escape pressed during create - loop back to menu
# Escape pressed during create or back from detail - loop back to menu
}
1 { manage_instances } # loops back to this menu after returning
2 { exit 0 } # Exit option
@ -907,11 +924,12 @@ function main_menu_for_existing {
}
else {
# All containers were deleted - go straight to install
$script:CreatedContainerName = ''
$result = create_instance
if (-not $result) {
exit 0
}
return
manage_single_instance -ContainerName $script:CreatedContainerName
}
}
}
@ -931,10 +949,12 @@ function main {
else {
# No existing containers - go straight to install.
# If Escape pressed during create, exit gracefully.
$script:CreatedContainerName = ''
$result = create_instance
if (-not $result) {
exit 0
}
manage_single_instance -ContainerName $script:CreatedContainerName
}
}

View file

@ -348,6 +348,28 @@ check_docker() {
fi
}
wait_for_ready() {
URL="$1"
MAX_WAIT=60
WAITED=0
printf "${GREEN}[INFO]${NC} Launching Agent Zero..."
while [ "$WAITED" -lt "$MAX_WAIT" ]; do
HTTP_CODE="$(curl -s -o /dev/null -w '%{http_code}' "$URL" 2>/dev/null || true)"
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 400 ]; then
printf "\n"
print_ok "Agent Zero is ready at $URL"
return 0
fi
sleep 1
WAITED=$((WAITED + 1))
printf "."
done
printf "\n"
print_warn "Agent Zero did not respond within ${MAX_WAIT} seconds. It may still be starting up."
return 1
}
count_existing_agent_zero_containers() {
docker ps -a --format '{{.Names}}|{{.Image}}' 2>/dev/null | awk -F'|' '$2 ~ /^agent0ai\/agent-zero(:|$)/ {count++} END {print count+0}'
}
@ -627,33 +649,12 @@ create_instance() {
docker compose -f "$COMPOSE_FILE" up -d
# -----------------------------------------------------------
# 5. Done!
# 5. Wait for the service to become ready
# -----------------------------------------------------------
echo ""
echo "=========================================="
printf " ${GREEN}${BOLD}Installation Complete!${NC}\n"
echo "=========================================="
echo ""
echo " 🏷️ Image tag : $SELECTED_TAG"
echo " 📦 Instance name : $CONTAINER_NAME"
echo " 🧩 Compose file : $COMPOSE_FILE"
echo " 📁 Data directory : $DATA_DIR"
echo " 🌐 Web UI : http://localhost:$PORT"
if [ -n "$AUTH_LOGIN" ]; then
echo " 🔐 Authentication : enabled"
echo " 👤 Login : $AUTH_LOGIN"
echo " 🔑 Password : $AUTH_PASSWORD"
else
echo " 🔓 Authentication : none"
fi
echo ""
echo " Useful commands:"
echo " docker compose -f $COMPOSE_FILE logs -f # View logs"
echo " docker compose -f $COMPOSE_FILE down # Stop"
echo " docker compose -f $COMPOSE_FILE up -d # Start"
echo " docker compose -f $COMPOSE_FILE pull # Update image"
echo ""
print_info "Happy automating with Agent Zero! 🤖"
wait_for_ready "http://localhost:$PORT"
# Store the created container name for the caller
CREATED_CONTAINER_NAME="$CONTAINER_NAME"
}
manage_instances() {
@ -744,120 +745,131 @@ manage_instances() {
SELECTED_IMAGE="$(printf "%s\n" "$SELECTED_ROW" | cut -d'|' -f2)"
SELECTED_STATUS="$(printf "%s\n" "$SELECTED_ROW" | cut -d'|' -f3-)"
while :; do
SELECTED_STATUS="$(docker ps -a --filter "name=^/${SELECTED_NAME}$" --format '{{.Status}}' 2>/dev/null | head -n 1)"
manage_single_instance "$SELECTED_NAME"
done
}
# If container no longer exists (e.g. after delete), go back to instance list
if [ -z "$SELECTED_STATUS" ]; then
# Show the action menu for a single container (open, start, stop, restart, delete).
# Can be called from manage_instances or directly after create_instance.
manage_single_instance() {
SELECTED_NAME="$1"
# Look up the image for display
SELECTED_IMAGE="$(docker ps -a --filter "name=^/${SELECTED_NAME}$" --format '{{.Image}}' 2>/dev/null | head -n 1)"
while :; do
SELECTED_STATUS="$(docker ps -a --filter "name=^/${SELECTED_NAME}$" --format '{{.Status}}' 2>/dev/null | head -n 1)"
# If container no longer exists (e.g. after delete), return
if [ -z "$SELECTED_STATUS" ]; then
break
fi
case "$SELECTED_STATUS" in
Up*) IS_RUNNING=1 ;;
*) IS_RUNNING=0 ;;
esac
INSTANCE_HEADER="Selected: $SELECTED_NAME ($SELECTED_IMAGE, $SELECTED_STATUS)"
if [ "$IS_RUNNING" -eq 1 ]; then
ACTION_INDEX=$(select_from_menu "--header=$INSTANCE_HEADER" "Open in browser" "Restart" "Stop" "Delete" "Back") || true
case "$ACTION_INDEX" in
-1) ACTION_KEY="back" ;; # Escape/Backspace — go back
0) ACTION_KEY="open" ;;
1) ACTION_KEY="restart" ;;
2) ACTION_KEY="stop" ;;
3) ACTION_KEY="delete" ;;
4) ACTION_KEY="back" ;;
*) ACTION_KEY="invalid" ;;
esac
else
ACTION_INDEX=$(select_from_menu "--header=$INSTANCE_HEADER" "Start" "Delete" "Back") || true
case "$ACTION_INDEX" in
-1) ACTION_KEY="back" ;; # Escape/Backspace — go back
0) ACTION_KEY="start" ;;
1) ACTION_KEY="delete" ;;
2) ACTION_KEY="back" ;;
*) ACTION_KEY="invalid" ;;
esac
fi
case "$ACTION_KEY" in
open)
PORT_OUTPUT="$(docker port "$SELECTED_NAME" 80/tcp 2>/dev/null || true)"
HOST_PORT="$(printf "%s\n" "$PORT_OUTPUT" | sed -n 's/.*:\([0-9][0-9]*\)$/\1/p' | head -n 1)"
if [ -z "$HOST_PORT" ]; then
print_warn "Could not resolve a host port for '$SELECTED_NAME' on 80/tcp. Ensure it is running with a published port."
else
TARGET_URL="http://localhost:$HOST_PORT"
print_info "Opening $TARGET_URL"
open_browser "$TARGET_URL"
fi
wait_for_keypress
;;
start)
print_info "Starting '$SELECTED_NAME'..."
START_OUTPUT="$(docker start "$SELECTED_NAME" 2>&1)" || true
if docker ps --filter "name=^/${SELECTED_NAME}$" --filter "status=running" --format '{{.Names}}' 2>/dev/null | grep -q "^${SELECTED_NAME}$"; then
print_ok "Started '$SELECTED_NAME'."
else
print_error "Failed to start '$SELECTED_NAME'."
if [ -n "$START_OUTPUT" ]; then
printf " %s\n" "$START_OUTPUT"
fi
fi
wait_for_keypress
;;
stop)
print_info "Stopping '$SELECTED_NAME'..."
if docker stop "$SELECTED_NAME" >/dev/null 2>&1; then
print_ok "Stopped '$SELECTED_NAME'."
else
print_error "Failed to stop '$SELECTED_NAME'."
fi
wait_for_keypress
;;
restart)
print_info "Restarting '$SELECTED_NAME'..."
RESTART_OUTPUT="$(docker restart "$SELECTED_NAME" 2>&1)" || true
if docker ps --filter "name=^/${SELECTED_NAME}$" --filter "status=running" --format '{{.Names}}' 2>/dev/null | grep -q "^${SELECTED_NAME}$"; then
print_ok "Restarted '$SELECTED_NAME'."
else
print_error "Failed to restart '$SELECTED_NAME'."
if [ -n "$RESTART_OUTPUT" ]; then
printf " %s\n" "$RESTART_OUTPUT"
fi
fi
wait_for_keypress
;;
delete)
printf "Are you sure you want to delete '%s'? [y/N]: " "$SELECTED_NAME"
IFS= read -rsn1 CONFIRM </dev/tty
printf "\n"
if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
# Stop first if running
docker stop "$SELECTED_NAME" >/dev/null 2>&1 || true
if docker rm "$SELECTED_NAME" >/dev/null 2>&1; then
print_ok "Deleted '$SELECTED_NAME'."
else
print_error "Failed to delete '$SELECTED_NAME'."
fi
wait_for_keypress
break # Container no longer exists
else
print_info "Delete cancelled."
wait_for_keypress
fi
;;
back)
break
fi
case "$SELECTED_STATUS" in
Up*) IS_RUNNING=1 ;;
*) IS_RUNNING=0 ;;
esac
INSTANCE_HEADER="Selected: $SELECTED_NAME ($SELECTED_IMAGE, $SELECTED_STATUS)"
if [ "$IS_RUNNING" -eq 1 ]; then
ACTION_INDEX=$(select_from_menu "--header=$INSTANCE_HEADER" "Open in browser" "Restart" "Stop" "Delete" "Back") || true
case "$ACTION_INDEX" in
-1) ACTION_KEY="back" ;; # Escape/Backspace — go back to instance list
0) ACTION_KEY="open" ;;
1) ACTION_KEY="restart" ;;
2) ACTION_KEY="stop" ;;
3) ACTION_KEY="delete" ;;
4) ACTION_KEY="back" ;;
*) ACTION_KEY="invalid" ;;
esac
else
ACTION_INDEX=$(select_from_menu "--header=$INSTANCE_HEADER" "Start" "Delete" "Back") || true
case "$ACTION_INDEX" in
-1) ACTION_KEY="back" ;; # Escape/Backspace — go back to instance list
0) ACTION_KEY="start" ;;
1) ACTION_KEY="delete" ;;
2) ACTION_KEY="back" ;;
*) ACTION_KEY="invalid" ;;
esac
fi
case "$ACTION_KEY" in
open)
PORT_OUTPUT="$(docker port "$SELECTED_NAME" 80/tcp 2>/dev/null || true)"
HOST_PORT="$(printf "%s\n" "$PORT_OUTPUT" | sed -n 's/.*:\([0-9][0-9]*\)$/\1/p' | head -n 1)"
if [ -z "$HOST_PORT" ]; then
print_warn "Could not resolve a host port for '$SELECTED_NAME' on 80/tcp. Ensure it is running with a published port."
else
TARGET_URL="http://localhost:$HOST_PORT"
print_info "Opening $TARGET_URL"
open_browser "$TARGET_URL"
fi
wait_for_keypress
;;
start)
print_info "Starting '$SELECTED_NAME'..."
START_OUTPUT="$(docker start "$SELECTED_NAME" 2>&1)" || true
if docker ps --filter "name=^/${SELECTED_NAME}$" --filter "status=running" --format '{{.Names}}' 2>/dev/null | grep -q "^${SELECTED_NAME}$"; then
print_ok "Started '$SELECTED_NAME'."
else
print_error "Failed to start '$SELECTED_NAME'."
if [ -n "$START_OUTPUT" ]; then
printf " %s\n" "$START_OUTPUT"
fi
fi
wait_for_keypress
;;
stop)
print_info "Stopping '$SELECTED_NAME'..."
if docker stop "$SELECTED_NAME" >/dev/null 2>&1; then
print_ok "Stopped '$SELECTED_NAME'."
else
print_error "Failed to stop '$SELECTED_NAME'."
fi
wait_for_keypress
;;
restart)
print_info "Restarting '$SELECTED_NAME'..."
RESTART_OUTPUT="$(docker restart "$SELECTED_NAME" 2>&1)" || true
if docker ps --filter "name=^/${SELECTED_NAME}$" --filter "status=running" --format '{{.Names}}' 2>/dev/null | grep -q "^${SELECTED_NAME}$"; then
print_ok "Restarted '$SELECTED_NAME'."
else
print_error "Failed to restart '$SELECTED_NAME'."
if [ -n "$RESTART_OUTPUT" ]; then
printf " %s\n" "$RESTART_OUTPUT"
fi
fi
wait_for_keypress
;;
delete)
printf "Are you sure you want to delete '%s'? [y/N]: " "$SELECTED_NAME"
IFS= read -rsn1 CONFIRM </dev/tty
printf "\n"
if [ "$CONFIRM" = "y" ] || [ "$CONFIRM" = "Y" ]; then
# Stop first if running
docker stop "$SELECTED_NAME" >/dev/null 2>&1 || true
if docker rm "$SELECTED_NAME" >/dev/null 2>&1; then
print_ok "Deleted '$SELECTED_NAME'."
else
print_error "Failed to delete '$SELECTED_NAME'."
fi
wait_for_keypress
break # Back to instance list (container no longer exists)
else
print_info "Delete cancelled."
wait_for_keypress
fi
;;
back)
break # Break inner loop, go back to instance selection
;;
*)
print_warn "Invalid action. Please try again."
wait_for_keypress
;;
esac
done
;;
*)
print_warn "Invalid action. Please try again."
wait_for_keypress
;;
esac
done
}
@ -876,10 +888,11 @@ main_menu_for_existing() {
case "$SELECTED_INDEX" in
-1) exit 0 ;; # Escape/Backspace — exit
0)
CREATED_CONTAINER_NAME=""
if create_instance; then
return 0 # Install completed successfully
manage_single_instance "$CREATED_CONTAINER_NAME"
fi
# Escape pressed during create — loop back to menu
# Escape pressed during create or back from detail — loop back to menu
;;
1) manage_instances ;; # loops back to this menu after returning
2) exit 0 ;; # Exit option
@ -887,10 +900,11 @@ main_menu_for_existing() {
esac
else
# All containers were deleted — go straight to install
CREATED_CONTAINER_NAME=""
if ! create_instance; then
exit 0
fi
return 0
manage_single_instance "$CREATED_CONTAINER_NAME"
fi
done
}
@ -909,9 +923,11 @@ main() {
else
# No existing containers — go straight to install.
# If Escape pressed during create, exit gracefully.
CREATED_CONTAINER_NAME=""
if ! create_instance; then
exit 0
fi
manage_single_instance "$CREATED_CONTAINER_NAME"
fi
}