#!/usr/bin/env sh # Linux offline deployment using the extracted single release archive. set -eu if [ "${1:-}" = '--env-file-only' ]; then export DEPLOY_API_ENV_FILE_ONLY=1 shift fi CALLER_DIR=$(pwd) case "$0" in */*) SCRIPT_DIR=${0%/*} ;; *) SCRIPT_DIR=. ;; esac REPO_ROOT=$(CDPATH= cd -- "$SCRIPT_DIR" && pwd) cd "$REPO_ROOT" ACTION=${1:-deploy} case "$ACTION" in help|-h|--help) echo 'Optional first argument: --env-file-only (QCC/DeepSeek and DMS connection settings from .env; direct process restart inherits; systemd needs unit configuration)' echo 'Example: sh deploy-offline.sh --env-file-only check-qcc "company full name"' echo 'Usage: sh deploy-offline.sh [deploy|import-knowledge|restart|start|stop|status|check-milvus|check-redis|check-dms|check-deepseek|check-qcc "company full name"|check "company full name"]' echo 'deploy: use the preinstalled .venv and packaged snapshot; never download' echo 'Usage: sh deploy-offline.sh import-knowledge [ZIP_PATH [DATABASE]]' echo 'Talent: sh deploy-offline.sh import-knowledge ZIP_PATH [DATABASE] --agent talent [--db-prefix talent_knowledge]' echo 'The agent selects a separate prepared directory and database prefix; mismatched packages are rejected.' echo 'import-knowledge: replace the full snapshot, or only the named library; preserve old versions' echo 'DATABASE: policy | finance | qa | article | service_guide | service_catalog' echo 'ZIP_PATH defaults to output/knowledge-snapshot.zip; relative paths use the caller directory' echo 'Configuration and prerequisites: docs/deployment.md' exit 0 ;; deploy|import-knowledge|restart|start|stop|status|serve|check|check-milvus|check-redis|check-dms|check-deepseek|check-qcc) ;; *) echo 'Unknown offline deployment action.' >&2; exit 2 ;; esac case "$ACTION" in check|check-qcc) [ "$#" -eq 2 ] && [ -n "$2" ] || { echo 'This check requires one exact company name.' >&2; exit 2; } ;; import-knowledge) # Preserve argument boundaries while resolving only the optional ZIP path. shift if [ "$#" -gt 0 ]; then case "$1" in --*) echo 'ZIP_PATH must precede target options.' >&2; exit 2 ;; esac [ -n "$1" ] || { echo 'ZIP_PATH must not be empty.' >&2; exit 2; } case "$1" in /*) KNOWLEDGE_ZIP=$1 ;; *) KNOWLEDGE_ZIP=$CALLER_DIR/$1 ;; esac shift set -- "$KNOWLEDGE_ZIP" "$@" fi # Validate before invoking Python (also works in offline shell probes). IMPORT_POSITION=0 EXPECT_VALUE='' for IMPORT_ARG in "$@"; do IMPORT_POSITION=$((IMPORT_POSITION + 1)) if [ "$IMPORT_POSITION" -eq 1 ]; then continue; fi if [ -n "$EXPECT_VALUE" ]; then case "$EXPECT_VALUE:$IMPORT_ARG" in agent:business|agent:talent) ;; prefix:*) case "$IMPORT_ARG" in ''|*[!A-Za-z0-9_]*|[!A-Za-z]*) echo 'Invalid database prefix.' >&2; exit 2 ;; esac ;; *) echo 'Invalid knowledge target.' >&2; exit 2 ;; esac EXPECT_VALUE='' else case "$IMPORT_ARG" in --agent) EXPECT_VALUE=agent ;; --db-prefix) EXPECT_VALUE=prefix ;; policy|finance|qa|article|service_guide|service_catalog) [ "$IMPORT_POSITION" -eq 2 ] || { echo 'Library must follow ZIP_PATH.' >&2; exit 2; } ;; *) echo 'Unknown knowledge import argument.' >&2; exit 2 ;; esac fi done [ -z "$EXPECT_VALUE" ] || { echo 'Missing knowledge target value.' >&2; exit 2; } ;; *) [ "$#" -le 1 ] || { echo 'Only one action is accepted.' >&2; exit 2; } ;; esac [ "$(uname -s)" = Linux ] || { echo 'deploy-offline.sh requires Linux.' >&2; exit 2; } export DEPLOY_OFFLINE=1 HF_HUB_OFFLINE=1 TRANSFORMERS_OFFLINE=1 export EMBEDDING_MODEL_PATH="$REPO_ROOT/models/bge-large-zh-v1.5" SERVICE_PYTHON="$REPO_ROOT/.venv/bin/python" [ -x "$SERVICE_PYTHON" ] || { echo 'Offline deployment requires the preinstalled .venv/bin/python.' >&2; exit 1; } case "$ACTION" in check|check-qcc) exec "$SERVICE_PYTHON" scripts/deploy.py "$ACTION" "$2" ;; import-knowledge) exec "$SERVICE_PYTHON" scripts/deploy.py "$ACTION" "$@" ;; esac exec "$SERVICE_PYTHON" scripts/deploy.py "$ACTION"