mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-06-02 00:57:41 +08:00
refactor: simplify run.sh by extracting shared logic and eliminating duplication
This commit is contained in:
603
run.sh
603
run.sh
@@ -9,7 +9,6 @@ set -e
|
|||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
YELLOW='\033[0;33m'
|
YELLOW='\033[0;33m'
|
||||||
BLUE='\033[0;34m'
|
|
||||||
CYAN='\033[0;36m'
|
CYAN='\033[0;36m'
|
||||||
BOLD='\033[1m'
|
BOLD='\033[1m'
|
||||||
NC='\033[0m'
|
NC='\033[0m'
|
||||||
@@ -159,20 +158,18 @@ clone_project() {
|
|||||||
|
|
||||||
if ! command -v git &> /dev/null; then
|
if ! command -v git &> /dev/null; then
|
||||||
echo -e "${YELLOW}⚠️ Git not available. Trying wget/curl...${NC}"
|
echo -e "${YELLOW}⚠️ Git not available. Trying wget/curl...${NC}"
|
||||||
|
local zip_url="https://gitee.com/zhayujie/chatgpt-on-wechat/repository/archive/master.zip"
|
||||||
if command -v wget &> /dev/null; then
|
if command -v wget &> /dev/null; then
|
||||||
wget https://gitee.com/zhayujie/chatgpt-on-wechat/repository/archive/master.zip -O chatgpt-on-wechat.zip
|
wget "$zip_url" -O chatgpt-on-wechat.zip
|
||||||
unzip chatgpt-on-wechat.zip
|
|
||||||
mv chatgpt-on-wechat-master chatgpt-on-wechat
|
|
||||||
rm chatgpt-on-wechat.zip
|
|
||||||
elif command -v curl &> /dev/null; then
|
elif command -v curl &> /dev/null; then
|
||||||
curl -L https://gitee.com/zhayujie/chatgpt-on-wechat/repository/archive/master.zip -o chatgpt-on-wechat.zip
|
curl -L "$zip_url" -o chatgpt-on-wechat.zip
|
||||||
unzip chatgpt-on-wechat.zip
|
|
||||||
mv chatgpt-on-wechat-master chatgpt-on-wechat
|
|
||||||
rm chatgpt-on-wechat.zip
|
|
||||||
else
|
else
|
||||||
echo -e "${RED}❌ Cannot download project. Please install Git, wget, or curl.${NC}"
|
echo -e "${RED}❌ Cannot download project. Please install Git, wget, or curl.${NC}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
unzip chatgpt-on-wechat.zip
|
||||||
|
mv chatgpt-on-wechat-master chatgpt-on-wechat
|
||||||
|
rm chatgpt-on-wechat.zip
|
||||||
else
|
else
|
||||||
git clone https://github.com/zhayujie/chatgpt-on-wechat.git || \
|
git clone https://github.com/zhayujie/chatgpt-on-wechat.git || \
|
||||||
git clone https://gitee.com/zhayujie/chatgpt-on-wechat.git
|
git clone https://gitee.com/zhayujie/chatgpt-on-wechat.git
|
||||||
@@ -198,69 +195,52 @@ clone_project() {
|
|||||||
# Install dependencies
|
# Install dependencies
|
||||||
install_dependencies() {
|
install_dependencies() {
|
||||||
echo -e "${GREEN}📦 Installing dependencies...${NC}"
|
echo -e "${GREEN}📦 Installing dependencies...${NC}"
|
||||||
|
local PIP_MIRROR="-i https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||||
# For Python 3.11+, use --break-system-packages to avoid externally-managed-environment errors
|
|
||||||
PIP_EXTRA_ARGS=""
|
PIP_EXTRA_ARGS=""
|
||||||
if $PYTHON_CMD -c "import sys; exit(0 if sys.version_info >= (3, 11) else 1)" 2>/dev/null; then
|
if $PYTHON_CMD -c "import sys; exit(0 if sys.version_info >= (3, 11) else 1)" 2>/dev/null; then
|
||||||
PIP_EXTRA_ARGS="--break-system-packages"
|
PIP_EXTRA_ARGS="--break-system-packages"
|
||||||
echo -e "${YELLOW}Python 3.11+ detected, using --break-system-packages for pip installations${NC}"
|
echo -e "${YELLOW}Python 3.11+ detected, using --break-system-packages for pip installations${NC}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Upgrade pip and basic tools (ignore existing system packages to avoid conflicts)
|
|
||||||
echo -e "${YELLOW}Upgrading pip and basic tools...${NC}"
|
echo -e "${YELLOW}Upgrading pip and basic tools...${NC}"
|
||||||
set +e
|
set +e
|
||||||
$PYTHON_CMD -m pip install --upgrade pip setuptools wheel importlib_metadata --ignore-installed $PIP_EXTRA_ARGS -i https://pypi.tuna.tsinghua.edu.cn/simple > /tmp/pip_upgrade.log 2>&1
|
$PYTHON_CMD -m pip install --upgrade pip setuptools wheel importlib_metadata --ignore-installed $PIP_EXTRA_ARGS $PIP_MIRROR > /tmp/pip_upgrade.log 2>&1
|
||||||
if [ $? -ne 0 ]; then
|
[ $? -ne 0 ] && echo -e "${YELLOW}⚠️ Some tools failed to upgrade, but continuing...${NC}"
|
||||||
echo -e "${YELLOW}⚠️ Some tools failed to upgrade, but continuing...${NC}"
|
|
||||||
cat /tmp/pip_upgrade.log | head -20
|
|
||||||
fi
|
|
||||||
set -e
|
set -e
|
||||||
rm -f /tmp/pip_upgrade.log
|
rm -f /tmp/pip_upgrade.log
|
||||||
|
|
||||||
# Common packages that may have distutils/system conflicts
|
|
||||||
COMMON_CONFLICT_PACKAGES="PyYAML setuptools wheel certifi charset-normalizer"
|
|
||||||
|
|
||||||
# Try normal installation first
|
|
||||||
echo -e "${YELLOW}Installing project dependencies...${NC}"
|
echo -e "${YELLOW}Installing project dependencies...${NC}"
|
||||||
|
set +e
|
||||||
# Save output and capture exit code correctly
|
$PYTHON_CMD -m pip install -r requirements.txt $PIP_EXTRA_ARGS $PIP_MIRROR > /tmp/pip_install.log 2>&1
|
||||||
set +e # Temporarily disable exit on error
|
local exit_code=$?
|
||||||
$PYTHON_CMD -m pip install -r requirements.txt $PIP_EXTRA_ARGS -i https://pypi.tuna.tsinghua.edu.cn/simple > /tmp/pip_install.log 2>&1
|
set -e
|
||||||
INSTALL_EXIT_CODE=$?
|
|
||||||
set -e # Re-enable exit on error
|
|
||||||
|
|
||||||
# Show output
|
|
||||||
cat /tmp/pip_install.log
|
cat /tmp/pip_install.log
|
||||||
|
|
||||||
if [ $INSTALL_EXIT_CODE -eq 0 ]; then
|
if [ $exit_code -eq 0 ]; then
|
||||||
echo -e "${GREEN}✅ Dependencies installed successfully.${NC}"
|
echo -e "${GREEN}✅ Dependencies installed successfully.${NC}"
|
||||||
|
elif grep -qE "distutils installed project|uninstall-no-record-file|installed by debian" /tmp/pip_install.log; then
|
||||||
|
echo -e "${YELLOW}⚠️ Detected system package conflict, retrying with workaround...${NC}"
|
||||||
|
local IGNORE_PACKAGES=""
|
||||||
|
for pkg in PyYAML setuptools wheel certifi charset-normalizer; do
|
||||||
|
IGNORE_PACKAGES="$IGNORE_PACKAGES --ignore-installed $pkg"
|
||||||
|
done
|
||||||
|
set +e
|
||||||
|
$PYTHON_CMD -m pip install -r requirements.txt $IGNORE_PACKAGES $PIP_EXTRA_ARGS $PIP_MIRROR \
|
||||||
|
&& echo -e "${GREEN}✅ Dependencies installed successfully (workaround applied).${NC}" \
|
||||||
|
|| echo -e "${YELLOW}⚠️ Some dependencies may have issues, but continuing...${NC}"
|
||||||
|
set -e
|
||||||
|
elif grep -q "externally-managed-environment" /tmp/pip_install.log; then
|
||||||
|
echo -e "${YELLOW}⚠️ Detected externally-managed environment, retrying with --break-system-packages...${NC}"
|
||||||
|
set +e
|
||||||
|
$PYTHON_CMD -m pip install -r requirements.txt --break-system-packages $PIP_MIRROR \
|
||||||
|
&& echo -e "${GREEN}✅ Dependencies installed successfully (system packages override applied).${NC}" \
|
||||||
|
|| echo -e "${YELLOW}⚠️ Some dependencies may have issues, but continuing...${NC}"
|
||||||
|
set -e
|
||||||
else
|
else
|
||||||
# Check if it's a distutils/system package conflict error
|
echo -e "${YELLOW}⚠️ Installation had errors, but continuing...${NC}"
|
||||||
if grep -qE "distutils installed project|uninstall-no-record-file|installed by debian" /tmp/pip_install.log; then
|
|
||||||
echo -e "${YELLOW}⚠️ Detected system package conflict, retrying with workaround...${NC}"
|
|
||||||
# Only ignore common conflict packages
|
|
||||||
IGNORE_PACKAGES=""
|
|
||||||
for pkg in $COMMON_CONFLICT_PACKAGES; do
|
|
||||||
IGNORE_PACKAGES="$IGNORE_PACKAGES --ignore-installed $pkg"
|
|
||||||
done
|
|
||||||
|
|
||||||
if $PYTHON_CMD -m pip install -r requirements.txt $IGNORE_PACKAGES $PIP_EXTRA_ARGS -i https://pypi.tuna.tsinghua.edu.cn/simple; then
|
|
||||||
echo -e "${GREEN}✅ Dependencies installed successfully (workaround applied).${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ Some dependencies may have issues, but continuing...${NC}"
|
|
||||||
fi
|
|
||||||
elif grep -q "externally-managed-environment" /tmp/pip_install.log; then
|
|
||||||
echo -e "${YELLOW}⚠️ Detected externally-managed environment, retrying with --break-system-packages...${NC}"
|
|
||||||
if $PYTHON_CMD -m pip install -r requirements.txt --break-system-packages -i https://pypi.tuna.tsinghua.edu.cn/simple; then
|
|
||||||
echo -e "${GREEN}✅ Dependencies installed successfully (system packages override applied).${NC}"
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ Some dependencies may have issues, but continuing...${NC}"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo -e "${YELLOW}⚠️ Installation had errors, but continuing...${NC}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -f /tmp/pip_install.log
|
rm -f /tmp/pip_install.log
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,108 +275,48 @@ select_model() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Read model config: provider, default_model, key_variable_name
|
||||||
|
read_model_config() {
|
||||||
|
local provider=$1 default_model=$2 key_var=$3
|
||||||
|
echo -e "${GREEN}Configuring ${provider}...${NC}"
|
||||||
|
read -p "Enter ${provider} API Key: " _api_key
|
||||||
|
read -p "Enter model name [press Enter for default: ${default_model}]: " model_name
|
||||||
|
model_name=${model_name:-$default_model}
|
||||||
|
MODEL_NAME="$model_name"
|
||||||
|
eval "${key_var}=\"\$_api_key\""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read optional API base URL
|
||||||
|
read_api_base() {
|
||||||
|
local base_var=$1 default_url=$2
|
||||||
|
read -p "Enter API Base URL [press Enter for default: ${default_url}]: " api_base
|
||||||
|
api_base=${api_base:-$default_url}
|
||||||
|
eval "${base_var}=\"\$api_base\""
|
||||||
|
}
|
||||||
|
|
||||||
# Configure model
|
# Configure model
|
||||||
configure_model() {
|
configure_model() {
|
||||||
case "$model_choice" in
|
case "$model_choice" in
|
||||||
1)
|
1) read_model_config "MiniMax" "MiniMax-M2.7" "MINIMAX_KEY" ;;
|
||||||
# MiniMax
|
2) read_model_config "Zhipu AI" "glm-5-turbo" "ZHIPU_KEY" ;;
|
||||||
echo -e "${GREEN}Configuring MiniMax...${NC}"
|
3) read_model_config "Kimi (Moonshot)" "kimi-k2.5" "MOONSHOT_KEY" ;;
|
||||||
read -p "Enter MiniMax API Key: " minimax_key
|
4) read_model_config "Doubao (Volcengine Ark)" "doubao-seed-2-0-code-preview-260215" "ARK_KEY" ;;
|
||||||
read -p "Enter model name [press Enter for default: MiniMax-M2.7]: " model_name
|
5) read_model_config "Qwen (DashScope)" "qwen3.5-plus" "DASHSCOPE_KEY" ;;
|
||||||
model_name=${model_name:-MiniMax-M2.7}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
MINIMAX_KEY="$minimax_key"
|
|
||||||
;;
|
|
||||||
2)
|
|
||||||
# Zhipu AI
|
|
||||||
echo -e "${GREEN}Configuring Zhipu AI...${NC}"
|
|
||||||
read -p "Enter Zhipu AI API Key: " zhipu_key
|
|
||||||
read -p "Enter model name [press Enter for default: glm-5-turbo]: " model_name
|
|
||||||
model_name=${model_name:-glm-5-turbo}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
ZHIPU_KEY="$zhipu_key"
|
|
||||||
;;
|
|
||||||
3)
|
|
||||||
# Kimi (Moonshot)
|
|
||||||
echo -e "${GREEN}Configuring Kimi (Moonshot)...${NC}"
|
|
||||||
read -p "Enter Moonshot API Key: " moonshot_key
|
|
||||||
read -p "Enter model name [press Enter for default: kimi-k2.5]: " model_name
|
|
||||||
model_name=${model_name:-kimi-k2.5}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
MOONSHOT_KEY="$moonshot_key"
|
|
||||||
;;
|
|
||||||
4)
|
|
||||||
# Doubao (Volcengine Ark)
|
|
||||||
echo -e "${GREEN}Configuring Doubao (Volcengine Ark)...${NC}"
|
|
||||||
read -p "Enter Ark API Key: " ark_key
|
|
||||||
read -p "Enter model name [press Enter for default: doubao-seed-2-0-code-preview-260215]: " model_name
|
|
||||||
model_name=${model_name:-doubao-seed-2-0-code-preview-260215}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
ARK_KEY="$ark_key"
|
|
||||||
;;
|
|
||||||
5)
|
|
||||||
# Qwen (DashScope)
|
|
||||||
echo -e "${GREEN}Configuring Qwen (DashScope)...${NC}"
|
|
||||||
read -p "Enter DashScope API Key: " dashscope_key
|
|
||||||
read -p "Enter model name [press Enter for default: qwen3.5-plus]: " model_name
|
|
||||||
model_name=${model_name:-qwen3.5-plus}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
DASHSCOPE_KEY="$dashscope_key"
|
|
||||||
;;
|
|
||||||
6)
|
6)
|
||||||
# Claude
|
read_model_config "Claude" "claude-sonnet-4-6" "CLAUDE_KEY"
|
||||||
echo -e "${GREEN}Configuring Claude...${NC}"
|
read_api_base "CLAUDE_BASE" "https://api.anthropic.com/v1"
|
||||||
read -p "Enter Claude API Key: " claude_key
|
|
||||||
read -p "Enter model name [press Enter for default: claude-sonnet-4-6]: " model_name
|
|
||||||
model_name=${model_name:-claude-sonnet-4-6}
|
|
||||||
read -p "Enter API Base URL [press Enter for default: https://api.anthropic.com/v1]: " api_base
|
|
||||||
api_base=${api_base:-https://api.anthropic.com/v1}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
CLAUDE_KEY="$claude_key"
|
|
||||||
CLAUDE_BASE="$api_base"
|
|
||||||
;;
|
;;
|
||||||
7)
|
7)
|
||||||
# Gemini
|
read_model_config "Gemini" "gemini-3.1-pro-preview" "GEMINI_KEY"
|
||||||
echo -e "${GREEN}Configuring Gemini...${NC}"
|
read_api_base "GEMINI_BASE" "https://generativelanguage.googleapis.com"
|
||||||
read -p "Enter Gemini API Key: " gemini_key
|
|
||||||
read -p "Enter model name [press Enter for default: gemini-3.1-pro-preview]: " model_name
|
|
||||||
model_name=${model_name:-gemini-3.1-pro-preview}
|
|
||||||
read -p "Enter API Base URL [press Enter for default: https://generativelanguage.googleapis.com]: " api_base
|
|
||||||
api_base=${api_base:-https://generativelanguage.googleapis.com}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
GEMINI_KEY="$gemini_key"
|
|
||||||
GEMINI_BASE="$api_base"
|
|
||||||
;;
|
;;
|
||||||
8)
|
8)
|
||||||
# OpenAI
|
read_model_config "OpenAI GPT" "gpt-5.4" "OPENAI_KEY"
|
||||||
echo -e "${GREEN}Configuring OpenAI GPT...${NC}"
|
read_api_base "OPENAI_BASE" "https://api.openai.com/v1"
|
||||||
read -p "Enter OpenAI API Key: " openai_key
|
|
||||||
read -p "Enter model name [press Enter for default: gpt-5.4]: " model_name
|
|
||||||
model_name=${model_name:-gpt-5.4}
|
|
||||||
read -p "Enter API Base URL [press Enter for default: https://api.openai.com/v1]: " api_base
|
|
||||||
api_base=${api_base:-https://api.openai.com/v1}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
OPENAI_KEY="$openai_key"
|
|
||||||
OPENAI_BASE="$api_base"
|
|
||||||
;;
|
;;
|
||||||
9)
|
9)
|
||||||
# LinkAI
|
read_model_config "LinkAI" "MiniMax-M2.7" "LINKAI_KEY"
|
||||||
echo -e "${GREEN}Configuring LinkAI...${NC}"
|
|
||||||
read -p "Enter LinkAI API Key: " linkai_key
|
|
||||||
read -p "Enter model name [press Enter for default: MiniMax-M2.7]: " model_name
|
|
||||||
model_name=${model_name:-MiniMax-M2.7}
|
|
||||||
|
|
||||||
MODEL_NAME="$model_name"
|
|
||||||
USE_LINKAI="true"
|
USE_LINKAI="true"
|
||||||
LINKAI_KEY="$linkai_key"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
@@ -514,227 +434,86 @@ configure_channel() {
|
|||||||
# Generate config file
|
# Generate config file
|
||||||
create_config_file() {
|
create_config_file() {
|
||||||
echo -e "${GREEN}📝 Generating config.json...${NC}"
|
echo -e "${GREEN}📝 Generating config.json...${NC}"
|
||||||
|
|
||||||
# Build JSON based on channel type
|
CHANNEL_TYPE="$CHANNEL_TYPE" \
|
||||||
case "$CHANNEL_TYPE" in
|
MODEL_NAME="$MODEL_NAME" \
|
||||||
feishu)
|
OPENAI_KEY="${OPENAI_KEY:-}" \
|
||||||
cat > config.json <<EOF
|
OPENAI_BASE="${OPENAI_BASE:-https://api.openai.com/v1}" \
|
||||||
{
|
CLAUDE_KEY="${CLAUDE_KEY:-}" \
|
||||||
"channel_type": "feishu",
|
CLAUDE_BASE="${CLAUDE_BASE:-https://api.anthropic.com/v1}" \
|
||||||
"model": "${MODEL_NAME}",
|
GEMINI_KEY="${GEMINI_KEY:-}" \
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
GEMINI_BASE="${GEMINI_BASE:-https://generativelanguage.googleapis.com}" \
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
ZHIPU_KEY="${ZHIPU_KEY:-}" \
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
MOONSHOT_KEY="${MOONSHOT_KEY:-}" \
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
ARK_KEY="${ARK_KEY:-}" \
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
DASHSCOPE_KEY="${DASHSCOPE_KEY:-}" \
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
MINIMAX_KEY="${MINIMAX_KEY:-}" \
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
USE_LINKAI="${USE_LINKAI:-false}" \
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
LINKAI_KEY="${LINKAI_KEY:-}" \
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
FEISHU_BOT_NAME="${FEISHU_BOT_NAME:-}" \
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
FEISHU_APP_ID="${FEISHU_APP_ID:-}" \
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
FEISHU_APP_SECRET="${FEISHU_APP_SECRET:-}" \
|
||||||
"voice_to_text": "openai",
|
WEB_PORT="${WEB_PORT:-}" \
|
||||||
"text_to_voice": "openai",
|
DT_CLIENT_ID="${DT_CLIENT_ID:-}" \
|
||||||
"voice_reply_voice": false,
|
DT_CLIENT_SECRET="${DT_CLIENT_SECRET:-}" \
|
||||||
"speech_recognition": true,
|
WECOM_BOT_ID="${WECOM_BOT_ID:-}" \
|
||||||
"group_speech_recognition": false,
|
WECOM_BOT_SECRET="${WECOM_BOT_SECRET:-}" \
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
QQ_APP_ID="${QQ_APP_ID:-}" \
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
QQ_APP_SECRET="${QQ_APP_SECRET:-}" \
|
||||||
"linkai_app_code": "",
|
WECHATCOM_CORP_ID="${WECHATCOM_CORP_ID:-}" \
|
||||||
"feishu_bot_name": "${FEISHU_BOT_NAME}",
|
WECHATCOM_TOKEN="${WECHATCOM_TOKEN:-}" \
|
||||||
"feishu_app_id": "${FEISHU_APP_ID}",
|
WECHATCOM_SECRET="${WECHATCOM_SECRET:-}" \
|
||||||
"feishu_app_secret": "${FEISHU_APP_SECRET}",
|
WECHATCOM_AGENT_ID="${WECHATCOM_AGENT_ID:-}" \
|
||||||
"dingtalk_client_id": "",
|
WECHATCOM_AES_KEY="${WECHATCOM_AES_KEY:-}" \
|
||||||
"dingtalk_client_secret": "",
|
WECHATCOM_PORT="${WECHATCOM_PORT:-}" \
|
||||||
"agent": true,
|
$PYTHON_CMD -c "
|
||||||
"agent_max_context_tokens": 40000,
|
import json, os
|
||||||
"agent_max_context_turns": 30,
|
e = os.environ.get
|
||||||
"agent_max_steps": 15
|
base = {
|
||||||
|
'channel_type': e('CHANNEL_TYPE'),
|
||||||
|
'model': e('MODEL_NAME'),
|
||||||
|
'open_ai_api_key': e('OPENAI_KEY', ''),
|
||||||
|
'open_ai_api_base': e('OPENAI_BASE'),
|
||||||
|
'claude_api_key': e('CLAUDE_KEY', ''),
|
||||||
|
'claude_api_base': e('CLAUDE_BASE'),
|
||||||
|
'gemini_api_key': e('GEMINI_KEY', ''),
|
||||||
|
'gemini_api_base': e('GEMINI_BASE'),
|
||||||
|
'zhipu_ai_api_key': e('ZHIPU_KEY', ''),
|
||||||
|
'moonshot_api_key': e('MOONSHOT_KEY', ''),
|
||||||
|
'ark_api_key': e('ARK_KEY', ''),
|
||||||
|
'dashscope_api_key': e('DASHSCOPE_KEY', ''),
|
||||||
|
'minimax_api_key': e('MINIMAX_KEY', ''),
|
||||||
|
'voice_to_text': 'openai',
|
||||||
|
'text_to_voice': 'openai',
|
||||||
|
'voice_reply_voice': False,
|
||||||
|
'speech_recognition': True,
|
||||||
|
'group_speech_recognition': False,
|
||||||
|
'use_linkai': e('USE_LINKAI') == 'true',
|
||||||
|
'linkai_api_key': e('LINKAI_KEY', ''),
|
||||||
|
'linkai_app_code': '',
|
||||||
|
'agent': True,
|
||||||
|
'agent_max_context_tokens': 40000,
|
||||||
|
'agent_max_context_turns': 30,
|
||||||
|
'agent_max_steps': 15,
|
||||||
}
|
}
|
||||||
EOF
|
channel_map = {
|
||||||
;;
|
'feishu': {'feishu_bot_name': 'FEISHU_BOT_NAME', 'feishu_app_id': 'FEISHU_APP_ID', 'feishu_app_secret': 'FEISHU_APP_SECRET'},
|
||||||
web)
|
'web': {'web_port': ('WEB_PORT', int)},
|
||||||
cat > config.json <<EOF
|
'dingtalk': {'dingtalk_client_id': 'DT_CLIENT_ID', 'dingtalk_client_secret': 'DT_CLIENT_SECRET'},
|
||||||
{
|
'wecom_bot': {'wecom_bot_id': 'WECOM_BOT_ID', 'wecom_bot_secret': 'WECOM_BOT_SECRET'},
|
||||||
"channel_type": "web",
|
'qq': {'qq_app_id': 'QQ_APP_ID', 'qq_app_secret': 'QQ_APP_SECRET'},
|
||||||
"web_port": ${WEB_PORT},
|
'wechatcom_app': {'wechatcom_corp_id': 'WECHATCOM_CORP_ID', 'wechatcomapp_token': 'WECHATCOM_TOKEN', 'wechatcomapp_secret': 'WECHATCOM_SECRET', 'wechatcomapp_agent_id': 'WECHATCOM_AGENT_ID', 'wechatcomapp_aes_key': 'WECHATCOM_AES_KEY', 'wechatcomapp_port': ('WECHATCOM_PORT', int)},
|
||||||
"model": "${MODEL_NAME}",
|
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
|
||||||
"voice_to_text": "openai",
|
|
||||||
"text_to_voice": "openai",
|
|
||||||
"voice_reply_voice": false,
|
|
||||||
"speech_recognition": true,
|
|
||||||
"group_speech_recognition": false,
|
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
|
||||||
"linkai_app_code": "",
|
|
||||||
"feishu_bot_name": "$feishu_bot_name",
|
|
||||||
"feishu_app_id": "",
|
|
||||||
"feishu_app_secret": "",
|
|
||||||
"dingtalk_client_id": "",
|
|
||||||
"dingtalk_client_secret": "",
|
|
||||||
"agent": true,
|
|
||||||
"agent_max_context_tokens": 40000,
|
|
||||||
"agent_max_context_turns": 30,
|
|
||||||
"agent_max_steps": 15
|
|
||||||
}
|
}
|
||||||
EOF
|
ch = e('CHANNEL_TYPE')
|
||||||
;;
|
for key, spec in channel_map.get(ch, {}).items():
|
||||||
dingtalk)
|
if isinstance(spec, tuple):
|
||||||
cat > config.json <<EOF
|
env_name, conv = spec
|
||||||
{
|
base[key] = conv(e(env_name))
|
||||||
"channel_type": "dingtalk",
|
else:
|
||||||
"model": "${MODEL_NAME}",
|
base[key] = e(spec, '')
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
with open('config.json', 'w') as f:
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
json.dump(base, f, indent=2, ensure_ascii=False)
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
"
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
|
||||||
"voice_to_text": "openai",
|
|
||||||
"text_to_voice": "openai",
|
|
||||||
"voice_reply_voice": false,
|
|
||||||
"speech_recognition": true,
|
|
||||||
"group_speech_recognition": false,
|
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
|
||||||
"linkai_app_code": "",
|
|
||||||
"feishu_bot_name": "$feishu_bot_name",
|
|
||||||
"feishu_app_id": "",
|
|
||||||
"feishu_app_secret": "",
|
|
||||||
"dingtalk_client_id": "${DT_CLIENT_ID}",
|
|
||||||
"dingtalk_client_secret": "${DT_CLIENT_SECRET}",
|
|
||||||
"agent": true,
|
|
||||||
"agent_max_context_tokens": 40000,
|
|
||||||
"agent_max_context_turns": 30,
|
|
||||||
"agent_max_steps": 15
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
wecom_bot)
|
|
||||||
cat > config.json <<EOF
|
|
||||||
{
|
|
||||||
"channel_type": "wecom_bot",
|
|
||||||
"wecom_bot_id": "${WECOM_BOT_ID}",
|
|
||||||
"wecom_bot_secret": "${WECOM_BOT_SECRET}",
|
|
||||||
"model": "${MODEL_NAME}",
|
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
|
||||||
"voice_to_text": "openai",
|
|
||||||
"text_to_voice": "openai",
|
|
||||||
"voice_reply_voice": false,
|
|
||||||
"speech_recognition": true,
|
|
||||||
"group_speech_recognition": false,
|
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
|
||||||
"linkai_app_code": "",
|
|
||||||
"agent": true,
|
|
||||||
"agent_max_context_tokens": 40000,
|
|
||||||
"agent_max_context_turns": 30,
|
|
||||||
"agent_max_steps": 15
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
qq)
|
|
||||||
cat > config.json <<EOF
|
|
||||||
{
|
|
||||||
"channel_type": "qq",
|
|
||||||
"qq_app_id": "${QQ_APP_ID}",
|
|
||||||
"qq_app_secret": "${QQ_APP_SECRET}",
|
|
||||||
"model": "${MODEL_NAME}",
|
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
|
||||||
"voice_to_text": "openai",
|
|
||||||
"text_to_voice": "openai",
|
|
||||||
"voice_reply_voice": false,
|
|
||||||
"speech_recognition": true,
|
|
||||||
"group_speech_recognition": false,
|
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
|
||||||
"linkai_app_code": "",
|
|
||||||
"agent": true,
|
|
||||||
"agent_max_context_tokens": 40000,
|
|
||||||
"agent_max_context_turns": 30,
|
|
||||||
"agent_max_steps": 15
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
wechatcom_app)
|
|
||||||
cat > config.json <<EOF
|
|
||||||
{
|
|
||||||
"channel_type": "wechatcom_app",
|
|
||||||
"wechatcom_corp_id": "${WECHATCOM_CORP_ID}",
|
|
||||||
"wechatcomapp_token": "${WECHATCOM_TOKEN}",
|
|
||||||
"wechatcomapp_secret": "${WECHATCOM_SECRET}",
|
|
||||||
"wechatcomapp_agent_id": "${WECHATCOM_AGENT_ID}",
|
|
||||||
"wechatcomapp_aes_key": "${WECHATCOM_AES_KEY}",
|
|
||||||
"wechatcomapp_port": ${WECHATCOM_PORT},
|
|
||||||
"model": "${MODEL_NAME}",
|
|
||||||
"open_ai_api_key": "${OPENAI_KEY:-}",
|
|
||||||
"open_ai_api_base": "${OPENAI_BASE:-https://api.openai.com/v1}",
|
|
||||||
"claude_api_key": "${CLAUDE_KEY:-}",
|
|
||||||
"claude_api_base": "${CLAUDE_BASE:-https://api.anthropic.com/v1}",
|
|
||||||
"gemini_api_key": "${GEMINI_KEY:-}",
|
|
||||||
"gemini_api_base": "${GEMINI_BASE:-https://generativelanguage.googleapis.com}",
|
|
||||||
"zhipu_ai_api_key": "${ZHIPU_KEY:-}",
|
|
||||||
"moonshot_api_key": "${MOONSHOT_KEY:-}",
|
|
||||||
"ark_api_key": "${ARK_KEY:-}",
|
|
||||||
"dashscope_api_key": "${DASHSCOPE_KEY:-}",
|
|
||||||
"minimax_api_key": "${MINIMAX_KEY:-}",
|
|
||||||
"voice_to_text": "openai",
|
|
||||||
"text_to_voice": "openai",
|
|
||||||
"voice_reply_voice": false,
|
|
||||||
"speech_recognition": true,
|
|
||||||
"group_speech_recognition": false,
|
|
||||||
"use_linkai": ${USE_LINKAI:-false},
|
|
||||||
"linkai_api_key": "${LINKAI_KEY:-}",
|
|
||||||
"linkai_app_code": "",
|
|
||||||
"feishu_bot_name": "$feishu_bot_name",
|
|
||||||
"feishu_app_id": "",
|
|
||||||
"feishu_app_secret": "",
|
|
||||||
"dingtalk_client_id": "",
|
|
||||||
"dingtalk_client_secret": "",
|
|
||||||
"agent": true,
|
|
||||||
"agent_max_context_tokens": 40000,
|
|
||||||
"agent_max_context_turns": 30,
|
|
||||||
"agent_max_steps": 15
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
echo -e "${GREEN}✅ Configuration file created successfully.${NC}"
|
echo -e "${GREEN}✅ Configuration file created successfully.${NC}"
|
||||||
}
|
}
|
||||||
@@ -811,23 +590,24 @@ show_usage() {
|
|||||||
echo -e "${CYAN}${BOLD}=========================================${NC}"
|
echo -e "${CYAN}${BOLD}=========================================${NC}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if service is running
|
# Ensure PYTHON_CMD is set
|
||||||
is_running() {
|
ensure_python_cmd() {
|
||||||
if [ -z "$PYTHON_CMD" ]; then
|
if [ -z "$PYTHON_CMD" ]; then
|
||||||
detect_python_command 2>/dev/null || PYTHON_CMD="python3"
|
detect_python_command 2>/dev/null || PYTHON_CMD="python3"
|
||||||
fi
|
fi
|
||||||
pid=$(ps ax | grep -i app.py | grep "${BASE_DIR}" | grep "$PYTHON_CMD" | grep -v grep | awk '{print $1}')
|
|
||||||
[ -n "$pid" ]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get service PID
|
# Get service PID (empty string if not running)
|
||||||
get_pid() {
|
get_pid() {
|
||||||
if [ -z "$PYTHON_CMD" ]; then
|
ensure_python_cmd
|
||||||
detect_python_command 2>/dev/null || PYTHON_CMD="python3"
|
|
||||||
fi
|
|
||||||
ps ax | grep -i app.py | grep "${BASE_DIR}" | grep "$PYTHON_CMD" | grep -v grep | awk '{print $1}'
|
ps ax | grep -i app.py | grep "${BASE_DIR}" | grep "$PYTHON_CMD" | grep -v grep | awk '{print $1}'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Check if service is running
|
||||||
|
is_running() {
|
||||||
|
[ -n "$(get_pid)" ]
|
||||||
|
}
|
||||||
|
|
||||||
# Start service
|
# Start service
|
||||||
cmd_start() {
|
cmd_start() {
|
||||||
# Check if config.json exists
|
# Check if config.json exists
|
||||||
@@ -1023,67 +803,38 @@ install_mode() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Require running inside the project directory
|
||||||
|
require_project_dir() {
|
||||||
|
if [ "$IS_PROJECT_DIR" = false ]; then
|
||||||
|
echo -e "${RED}${EMOJI_CROSS} Must run in project directory${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
# Main function
|
# Main function
|
||||||
main() {
|
main() {
|
||||||
case "$1" in
|
case "$1" in
|
||||||
start)
|
start|stop|restart|status|logs|config|update)
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
require_project_dir
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_start
|
|
||||||
;;
|
|
||||||
stop)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_stop
|
|
||||||
;;
|
|
||||||
restart)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_restart
|
|
||||||
;;
|
|
||||||
status)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_status
|
|
||||||
;;
|
|
||||||
logs)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_logs
|
|
||||||
;;
|
|
||||||
config)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_config
|
|
||||||
;;
|
|
||||||
update)
|
|
||||||
if [ "$IS_PROJECT_DIR" = false ]; then
|
|
||||||
echo -e "${RED}❌ Must run in project directory${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
cmd_update
|
|
||||||
;;
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
start) cmd_start ;;
|
||||||
|
stop) cmd_stop ;;
|
||||||
|
restart) cmd_restart ;;
|
||||||
|
status) cmd_status ;;
|
||||||
|
logs) cmd_logs ;;
|
||||||
|
config) cmd_config ;;
|
||||||
|
update) cmd_update ;;
|
||||||
help|--help|-h)
|
help|--help|-h)
|
||||||
show_usage
|
show_usage
|
||||||
;;
|
;;
|
||||||
"")
|
"")
|
||||||
# No command - install/configure mode
|
|
||||||
install_mode
|
install_mode
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo -e "${RED}❌ Unknown command: $1${NC}"
|
echo -e "${RED}${EMOJI_CROSS} Unknown command: $1${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
show_usage
|
show_usage
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
Reference in New Issue
Block a user