#!/usr/bin/env bash # Toggle Goose v1.49 canary routing on 103 stable Portal (.env). # users mode keeps the full native pool in TKMIND_API_TARGETS and only routes # allowlisted identities to TKMIND_API_TARGET_V149 (:18015 by default). set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" ENV_FILE="${GOOSE_V149_CANARY_ENV_FILE:-/Users/john/Project/Memind/.env}" MARKER_BEGIN='# GOOSE_V149_CANARY_BEGIN' MARKER_END='# GOOSE_V149_CANARY_END' V149_TARGET="${TKMIND_API_TARGET_V149:-https://127.0.0.1:18015}" PORTAL_LABEL="${MEMIND_PORTAL_LABEL:-cn.tkmind.memind-portal}" GUI="gui/$(id -u)" usage() { cat < Commands: on [all|users] Route allowlisted users (or everyone in all mode) to v1.49 canary (${V149_TARGET}) off|rollback Remove canary block from ${ENV_FILE} status Show active block users mode example (john only): TKMIND_GOOSE_CANARY_USERNAMES=john bash scripts/switch-goose-v149-canary-103.sh on users Notes: - Does not rewrite TKMIND_API_TARGETS or memory settings. - all mode is intended for local loopback canary only; avoid on the 9-instance 103 pool. EOF } backup_env() { cp "${ENV_FILE}" "${ENV_FILE}.bak-goose-v149-canary-$(date +%Y%m%d-%H%M%S)" } remove_canary_block() { awk -v begin="${MARKER_BEGIN}" -v end="${MARKER_END}" ' $0 == begin { skip=1; next } $0 == end { skip=0; next } skip == 0 { print } ' "${ENV_FILE}" > "${ENV_FILE}.tmp" mv "${ENV_FILE}.tmp" "${ENV_FILE}" } write_canary_block() { local mode="$1" backup_env remove_canary_block { echo "${MARKER_BEGIN}" echo "TKMIND_GOOSE_CANARY=${mode}" echo "TKMIND_API_TARGET_V149=${V149_TARGET}" if [[ "${mode}" == "all" ]]; then echo "TKMIND_API_TARGET=${V149_TARGET}" elif [[ "${mode}" == "users" ]]; then [[ -n "${TKMIND_GOOSE_CANARY_USER_IDS:-}" ]] && echo "TKMIND_GOOSE_CANARY_USER_IDS=${TKMIND_GOOSE_CANARY_USER_IDS}" [[ -n "${TKMIND_GOOSE_CANARY_USERNAMES:-}" ]] && echo "TKMIND_GOOSE_CANARY_USERNAMES=${TKMIND_GOOSE_CANARY_USERNAMES}" [[ -n "${TKMIND_GOOSE_CANARY_WECHAT_USER_IDS:-}" ]] && echo "TKMIND_GOOSE_CANARY_WECHAT_USER_IDS=${TKMIND_GOOSE_CANARY_WECHAT_USER_IDS}" fi echo "${MARKER_END}" } >> "${ENV_FILE}" } restart_portal() { launchctl kickstart -k "${GUI}/${PORTAL_LABEL}" 2>/dev/null || launchctl bootstrap "${GUI}" "${HOME}/Library/LaunchAgents/${PORTAL_LABEL}.plist" sleep 5 curl -fsS --connect-timeout 10 http://127.0.0.1:8081/api/status || echo "[goose-v149-canary-103] WARN: Portal /api/status not ready yet" >&2 } cmd="${1:-}" case "${cmd}" in on) mode="${2:-users}" if [[ ! -f "${ENV_FILE}" ]]; then echo "Missing ${ENV_FILE}" >&2 exit 1 fi if [[ "${mode}" == "all" ]]; then echo "[goose-v149-canary-103] WARN: all mode replaces the entire pool with v149; use users mode on 103 production" >&2 fi if [[ "${mode}" == "users" && -z "${TKMIND_GOOSE_CANARY_USER_IDS:-}${TKMIND_GOOSE_CANARY_USERNAMES:-}${TKMIND_GOOSE_CANARY_WECHAT_USER_IDS:-}" ]]; then echo "users mode requires identity allowlist env vars" >&2 exit 2 fi write_canary_block "${mode}" echo "[goose-v149-canary-103] enabled mode=${mode} in ${ENV_FILE}" restart_portal echo "[goose-v149-canary-103] Portal restarted" ;; off|rollback) backup_env remove_canary_block restart_portal echo "[goose-v149-canary-103] disabled; Portal on stable pool" ;; status) if grep -q "${MARKER_BEGIN}" "${ENV_FILE}" 2>/dev/null; then awk -v begin="${MARKER_BEGIN}" -v end="${MARKER_END}" ' $0 == begin { show=1; next } $0 == end { show=0; next } show == 1 { print } ' "${ENV_FILE}" else echo "[goose-v149-canary-103] no active block" fi ;; -h|--help|help|'') usage ;; *) echo "Unknown command: ${cmd}" >&2 usage exit 2 ;; esac