#!/usr/bin/env sh set -eu SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) INFRA_DIR=$(CDPATH= cd -- "$SCRIPT_DIR/.." && pwd) PLATFORM_ENV="${PLATFORM_ENV:-$INFRA_DIR/.env}" ASSISTANT_URL="${ASSISTANT_URL:-http://127.0.0.1:18082}" HUB_URL="${HUB_URL:-http://127.0.0.1:18081}" GATEWAY_URL="${GATEWAY_URL:-http://127.0.0.1:4100}" TASK_URL="${TASK_URL:-http://task.local.nodedc/}" ENGINE_URL="${ENGINE_URL:-http://127.0.0.1:5300/}" read_env() { file="$1" key="$2" if [ ! -f "$file" ]; then return 0 fi awk -F= -v key="$key" ' $0 ~ "^[[:space:]]*#" { next } $1 == key { value = substr($0, index($0, "=") + 1) gsub(/^[[:space:]]+|[[:space:]]+$/, "", value) gsub(/^"|"$/, "", value) print value exit } ' "$file" } http_status() { url="$1" curl -k -sS -o /dev/null -w "%{http_code}" --max-time 3 "$url" 2>/dev/null || true } http_body() { url="$1" curl -k -sS --max-time 3 "$url" 2>/dev/null || true } ok_status() { code="$1" case "$code" in 2*|3*) printf true ;; *) printf false ;; esac } json_number() { key="$1" sed -n "s/.*\"$key\"[[:space:]]*:[[:space:]]*\\([0-9][0-9]*\\).*/\\1/p" | head -n 1 } url_kind() { value="$1" case "$value" in "") printf missing ;; *127.0.0.1*|*localhost*|*host.docker.internal*|*".local.nodedc"*|*ai-workspace-hub*|*agent-gateway*) printf local ;; *100.[6-9][0-9].*|*100.1[01][0-9].*|*100.12[0-7].*|*.ts.net*) printf tailscale ;; *172.22.0.222*|*".nas.nodedc"*) printf synology-lan ;; *ai-hub.nodedc.ru*|*ops-agents.nodedc.ru*|*hub.nodedc.ru*|*ops.nodedc.ru*) printf prod-public ;; http://172.*|http://192.168.*|http://10.*) printf lan ;; *) printf custom ;; esac } bool_and() { left="$1" right="$2" if [ "$left" = true ] && [ "$right" = true ]; then printf true else printf false fi } assistant_code=$(http_status "$ASSISTANT_URL/healthz") hub_body=$(http_body "$HUB_URL/healthz") hub_code=000 if [ -n "$hub_body" ]; then hub_code=$(http_status "$HUB_URL/healthz") fi gateway_code=$(http_status "$GATEWAY_URL/readyz") task_code=$(http_status "$TASK_URL") engine_code=$(http_status "$ENGINE_URL") assistant_ok=$(ok_status "$assistant_code") hub_ok=$(ok_status "$hub_code") gateway_ok=$(ok_status "$gateway_code") task_ok=$(ok_status "$task_code") engine_ok=$(ok_status "$engine_code") agents_online=$(printf "%s" "$hub_body" | json_number agentsOnline) case "$agents_online" in ""|*[!0-9]*) agents_online=0 ;; esac hub_public=$(read_env "$PLATFORM_ENV" AI_WORKSPACE_HUB_PUBLIC_URL || true) hub_internal=$(read_env "$PLATFORM_ENV" AI_WORKSPACE_HUB_INTERNAL_URL || true) ops_entitlement=$(read_env "$PLATFORM_ENV" AI_WORKSPACE_OPS_ENTITLEMENT_URL || true) hub_public_kind=$(url_kind "$hub_public") hub_internal_kind=$(url_kind "$hub_internal") ops_entitlement_kind=$(url_kind "$ops_entitlement") local_services_ok=$(bool_and "$(bool_and "$assistant_ok" "$hub_ok")" "$(bool_and "$gateway_ok" "$task_ok")") worker_on_local_hub=false if [ "$agents_online" -gt 0 ]; then worker_on_local_hub=true fi hub_runtime_kind=custom case "$hub_public_kind:$hub_internal_kind" in local:local|local:missing|missing:local) hub_runtime_kind=local ;; tailscale:local|tailscale:tailscale|tailscale:missing) hub_runtime_kind=tailscale ;; prod-public:prod-public|prod-public:missing|missing:prod-public) hub_runtime_kind=prod-public ;; *) hub_runtime_kind=mixed ;; esac classification=contract-only if [ "$local_services_ok" = true ]; then if [ "$engine_ok" = true ] \ && [ "$worker_on_local_hub" = true ] \ && [ "$ops_entitlement_kind" = local ] \ && [ "$hub_runtime_kind" = local ]; then classification=true-local-e2e elif [ "$engine_ok" = true ] \ && [ "$worker_on_local_hub" = true ] \ && { [ "$ops_entitlement_kind" = tailscale ] || [ "$hub_runtime_kind" = tailscale ]; }; then classification=tunnel-local-e2e elif [ "$hub_runtime_kind" = prod-public ] || [ "$worker_on_local_hub" = false ]; then classification=hybrid-prod-bridge else classification=local-ops-vertical fi elif [ "$gateway_ok" = true ] && [ "$task_ok" = true ]; then classification=local-ops-vertical elif [ "$task_ok" = true ] || [ "$engine_ok" = true ]; then classification=local-ui-only fi cat <