#!/usr/bin/env bash # Toggle local Goose v1.49 canary for Portal dev (loopback only). # Does not modify 103/105 production. See docs/goose-v149-canary-runbook.md. set -euo pipefail ROOT="$(cd "$(dirname "$0")/.." && pwd)" ENV_FILE="${GOOSE_V149_CANARY_ENV_FILE:-${ROOT}/.env.local}" MARKER_BEGIN='# GOOSE_V149_CANARY_BEGIN' MARKER_END='# GOOSE_V149_CANARY_END' STABLE_TARGET="${TKMIND_API_TARGET_STABLE:-https://127.0.0.1:18006}" V149_TARGET="${TKMIND_API_TARGET_V149:-https://127.0.0.1:18049}" V149_PORT="${GOOSE_V149_PORT:-18049}" usage() { cat < Commands: on [all|users] Enable v1.49 canary (default: all → Portal uses ${V149_TARGET}) off|rollback Restore stable target (${STABLE_TARGET}) and disable canary flags status Print current canary block / env summary Env overrides: GOOSE_V149_CANARY_ENV_FILE Target env file (default: .env.local) TKMIND_GOOSE_CANARY_USER_IDS Comma-separated user IDs (users mode) TKMIND_GOOSE_CANARY_USERNAMES Comma-separated usernames (users mode) After "on", restart local Portal (pnpm dev) to pick up .env.local changes. EOF } remove_canary_block() { if [[ ! -f "${ENV_FILE}" ]]; then return 0 fi 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" remove_canary_block touch "${ENV_FILE}" { echo "${MARKER_BEGIN}" echo "TKMIND_GOOSE_CANARY=${mode}" echo "TKMIND_API_TARGET_STABLE=${STABLE_TARGET}" echo "TKMIND_API_TARGET_V149=${V149_TARGET}" if [[ "${mode}" == "all" ]]; then echo "TKMIND_API_TARGET=${V149_TARGET}" echo "TKMIND_API_TARGETS=" elif [[ "${mode}" == "users" ]]; then echo "TKMIND_API_TARGET=${STABLE_TARGET}" echo "TKMIND_API_TARGETS=${STABLE_TARGET},${V149_TARGET}" if [[ -n "${TKMIND_GOOSE_CANARY_USER_IDS:-}" ]]; then echo "TKMIND_GOOSE_CANARY_USER_IDS=${TKMIND_GOOSE_CANARY_USER_IDS}" fi if [[ -n "${TKMIND_GOOSE_CANARY_USERNAMES:-}" ]]; then echo "TKMIND_GOOSE_CANARY_USERNAMES=${TKMIND_GOOSE_CANARY_USERNAMES}" fi if [[ -n "${TKMIND_GOOSE_CANARY_WECHAT_USER_IDS:-}" ]]; then echo "TKMIND_GOOSE_CANARY_WECHAT_USER_IDS=${TKMIND_GOOSE_CANARY_WECHAT_USER_IDS}" fi fi echo "MEMORY_BACKEND=legacy" echo "MEMORY_VECTOR_ENABLED=0" echo "MEMORY_AGENT_INJECTION_MODE=off" echo "MEMORY_LIFECYCLE_ENABLED=0" echo "MEMORY_CANDIDATE_ENABLED=0" echo "MEMIND_PRODUCT_ANALYTICS_ENABLED=false" echo "H5_PUBLIC_BASE_URL=http://127.0.0.1:8081" echo "${MARKER_END}" } >> "${ENV_FILE}" } cmd="${1:-}" case "${cmd}" in on) mode="${2:-all}" if [[ "${mode}" != "all" && "${mode}" != "users" ]]; then echo "Invalid mode: ${mode} (expected all or users)" >&2 exit 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 TKMIND_GOOSE_CANARY_USER_IDS and/or USERNAMES / WECHAT_USER_IDS" >&2 exit 2 fi write_canary_block "${mode}" echo "[goose-v149-canary] enabled mode=${mode} env=${ENV_FILE}" echo "[goose-v149-canary] ensure v1.49 is running: bash scripts/run-goosed-v149-local.sh" echo "[goose-v149-canary] verify: curl -sk ${V149_TARGET}/status" ;; off|rollback) remove_canary_block echo "[goose-v149-canary] disabled; restored env block removed from ${ENV_FILE}" echo "[goose-v149-canary] Portal falls back to default TKMIND_API_TARGET (${STABLE_TARGET}) from .env" ;; status) if [[ -f "${ENV_FILE}" ]] && grep -q "${MARKER_BEGIN}" "${ENV_FILE}"; then echo "[goose-v149-canary] block present in ${ENV_FILE}:" awk -v begin="${MARKER_BEGIN}" -v end="${MARKER_END}" ' $0 == begin { show=1; next } $0 == end { show=0; next } show == 1 { print " " $0 } ' "${ENV_FILE}" else echo "[goose-v149-canary] no active block in ${ENV_FILE}" fi node "${ROOT}/scripts/goose-v149-canary.mjs" 2>/dev/null || true ;; -h|--help|help|'') usage [[ -z "${cmd}" ]] && exit 0 ;; *) echo "Unknown command: ${cmd}" >&2 usage exit 2 ;; esac