Files
hack/tools/scripts/llm-key-hunter/results/_cache/content/chongweiliu_slai-ascendbridge2.json
OpenCode 68a9071cf1 feat: reconcile local master with origin (exa/hot-platform hunters, leaks ledger, latest results)
Local branch had diverged from origin/master (sibling commits on the same base). Rewrote local history linearly on top of origin/master, folding in all local content: exa/hot-platform discovery hunters, leaks ledger, nightly sweep orchestrator, updated .gitignore and skill docs, plus the latest hunt output and vault state. Remote-only files (vault keys, channel scripts) were restored rather than dropped, so the resulting tree is a full union of both sides.
2026-08-07 12:53:47 +08:00

1 line
37 KiB
JSON

{"repo": "chongweiliu/slai-ascendbridge2", "files": {"scripts/install_claude_code.sh": {"523448fa9141fe978100b82163a8020071556329": {"t": 1785746434.7051742, "n": 10964, "h": "963d8134b3b1d152", "c": "#!/bin/bash\n\n# Claude Code 容器内一键安装脚本\n# 用法: bash install_claude_code.sh [模型名称] [API_KEY] [BASE_URL]\n# 交互模式 (不传参): 先弹提供方菜单(智谱/百炼/幻方/火山/MiniMax/Kimi/阶跃/Anthropic/自定义),\n# 选完后填模型名(带默认) → 填 API_KEY, URL 由所选提供方自动给出\n# 非交互示例:\n# bash install_claude_code.sh glm-4.6 sk-xxx # 前缀自动匹配智谱\n# bash install_claude_code.sh glm-4.6 sk-xxx https://open.bigmodel.cn/api/anthropic\n# bash install_claude_code.sh Qwen3-30B-A3B \"\" http://localhost:8000/v1\n# bash install_claude_code.sh MiniMax-M1 sk-xxx # 前缀自动匹配 minimax\n# CLAUDE_PROVIDER=bailian bash install_claude_code.sh deepseek-v3 sk-xxx # 百炼托管的任意模型\n# CLAUDE_PROVIDER=moonshot bash install_claude_code.sh kimi-k2 sk-xxx\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型名前缀 > 交互菜单\n# CLAUDE_PROVIDER 取值: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\n# 适配\"一个 API 支持多种模型\"的平台 (百炼/火山/MiniMax 等), URL 与模型名无关时用它最稳\n# 仿照智谱官方脚本 https://cdn.bigmodel.cn/install/claude_code_env.sh\n\nset -euo pipefail\n\n# ========================\n# 常量定义\n# ========================\nNODE_MIN_VERSION=18\nNODE_INSTALL_VERSION=22\nCLAUDE_PACKAGE=\"@anthropic-ai/claude-code\"\nAPI_TIMEOUT_MS=3000000\n\n# ========================\n# 工具函数\n# ========================\nlog_info() { echo \"🔹 $*\"; }\nlog_success() { echo \"✅ $*\"; }\nlog_error() { echo \"❌ $*\" >&2; }\n\n# ========================\n# 参数解析\n# ========================\n# ========================\n# 平台清单 (展示名 | provider key | 默认模型 | Anthropic 兼容 URL)\n# ========================\nPROVIDER_NAMES=(\n \"智谱 AI (GLM)\"\n \"阿里百炼 (Qwen)\"\n \"幻方 DeepSeek\"\n \"火山方舟 (豆包)\"\n \"MiniMax (M1/abab)\"\n \"月之暗面 (Kimi)\"\n \"阶跃星辰 (Step)\"\n \"Anthropic 官方\"\n \"自定义 (手动填 URL)\"\n)\nPROVIDER_KEYS=( \"zhipu\" \"bailian\" \"deepseek\" \"volcano\" \"minimax\" \"moonshot\" \"stepfun\" \"anthropic\" \"custom\" )\nPROVIDER_MODELS=(\"glm-4.6\" \"qwen3-coder-plus\" \"deepseek-v3\" \"doubao-seed-1-6-250615\" \"MiniMax-M1\" \"kimi-k2\" \"step-2\" \"claude-sonnet-4-5\" \"\" )\nPROVIDER_URLS=(\n \"https://open.bigmodel.cn/api/anthropic\"\n \"https://dashscope.aliyuncs.com/apps/anthropic\"\n \"https://api.deepseek.com/anthropic\"\n \"https://ark.cn-beijing.volces.com/api/coding\"\n \"https://api.minimaxi.com/anthropic\"\n \"https://api.moonshot.cn/anthropic\"\n \"https://api.stepfun.com/step_plan\"\n \"https://api.anthropic.com\"\n \"\"\n)\n\n# ========================\n# 平台(provider) → Anthropic 兼容 URL\n# ========================\nurl_for_provider() {\n case \"$1\" in\n anthropic|claude) echo \"https://api.anthropic.com\" ;;\n zhipu|glm) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n deepseek) echo \"https://api.deepseek.com/anthropic\" ;;\n bailian|dashscope|qwen) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n volcano|ark|doubao) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n minimax) echo \"https://api.minimaxi.com/anthropic\" ;;\n moonshot|kimi) echo \"https://api.moonshot.cn/anthropic\" ;;\n stepfun|step) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 模型名前缀 → Anthropic 兼容 URL (无 provider 时的回退)\n# ========================\nget_provider_url() {\n local model=\"${1,,}\" # 小写化后匹配, 兼容 Qwen3 / GLM-4.6 等大写写法\n case \"$model\" in\n claude-*) echo \"https://api.anthropic.com\" ;;\n deepseek-*) echo \"https://api.deepseek.com/anthropic\" ;;\n glm-*|chatglm-*) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n doubao-*) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n qwen*|qwq*) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n minimax-*|MiniMax-*|abab*) echo \"https://api.minimaxi.com/anthropic\" ;;\n kimi-*|moonshot-*) echo \"https://api.moonshot.cn/anthropic\" ;;\n step-*) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 交互式选择提供方菜单\n# ========================\nselect_provider_menu() {\n echo \"请选择模型提供方:\"\n local i=1\n for name in \"${PROVIDER_NAMES[@]}\"; do\n printf \" [%d] %s\\n\" \"$i\" \"$name\"\n i=$((i+1))\n done\n echo \" [0] 退出\"\n echo \"\"\n local choice\n read -e -p \"请选择 [1-${#PROVIDER_NAMES[@]}]: \" choice\n if [ -z \"$choice\" ] || [ \"$choice\" = \"0\" ]; then\n log_error \"未选择提供方\"; exit 1\n fi\n if ! [[ \"$choice\" =~ ^[0-9]+$ ]] || [ \"$choice\" -lt 1 ] || [ \"$choice\" -gt \"${#PROVIDER_NAMES[@]}\" ]; then\n log_error \"无效选择: $choice\"; exit 1\n fi\n local idx=$((choice-1))\n SELECTED_KEY=\"${PROVIDER_KEYS[$idx]}\"\n SELECTED_MODEL=\"${PROVIDER_MODELS[$idx]}\"\n SELECTED_URL=\"${PROVIDER_URLS[$idx]}\"\n}\n\n# ========================\n# 参数与提供方选择\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型前缀 > 交互菜单\n# ========================\nCUSTOM_URL=\"${3:-}\"\nPROVIDER=\"${CLAUDE_PROVIDER:-}\"\nMODEL=\"${1:-}\"\nAPI_KEY=\"${2:-}\"\n\n# 交互模式 (未传模型名且未指定 provider/url): 先选提供方, 再填模型与 key\nif [ -z \"$MODEL\" ] && [ -z \"$CUSTOM_URL\" ] && [ -z \"$PROVIDER\" ]; then\n select_provider_menu\n PROVIDER=\"$SELECTED_KEY\"\n if [ \"$PROVIDER\" = \"custom\" ]; then\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n else\n PROVIDER_URL=\"$SELECTED_URL\"\n fi\n read -e -p \"请输入模型名称 (默认 ${SELECTED_MODEL}): \" MODEL\n MODEL=\"${MODEL:-$SELECTED_MODEL}\"\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\nelse\n # 非交互: 位置参数 + 环境变量\n [ -z \"$MODEL\" ] && { read -e -p \"请输入模型名称 (默认 deepseek-v4-pro): \" MODEL; MODEL=\"${MODEL:-deepseek-v4-pro}\"; }\n if [ -z \"$API_KEY\" ]; then\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\n fi\n if [ -n \"$CUSTOM_URL\" ]; then\n PROVIDER_URL=\"$CUSTOM_URL\"\n elif [ -n \"$PROVIDER\" ]; then\n PROVIDER_URL=$(url_for_provider \"$PROVIDER\")\n if [ -z \"$PROVIDER_URL\" ]; then\n log_error \"未知 CLAUDE_PROVIDER: $PROVIDER\"\n echo \"支持: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\" >&2\n exit 1\n fi\n else\n PROVIDER_URL=$(get_provider_url \"$MODEL\")\n fi\n if [ -z \"$PROVIDER_URL\" ]; then\n echo \"\"\n echo \"模型 '${MODEL}' 不在已知前缀列表中。\"\n echo \"可选: 1) 显式传 BASE_URL; 2) 设 CLAUDE_PROVIDER=<平台>; 3) 下方手动输入\"\n echo \"已知前缀: claude-*, deepseek-*, glm-*, doubao-*, qwen*, minimax-*, abab*, kimi-*, moonshot-*, step-*\"\n echo \"已知 provider: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\"\n echo \"\"\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n fi\nfi\n\necho \"\"\necho \"========================================\"\necho \" 模型: ${MODEL}\"\n[ -n \"$PROVIDER\" ] && echo \" 平台: ${PROVIDER}\"\necho \" API URL: ${PROVIDER_URL}\"\necho \" API_KEY: ${API_KEY}\"\necho \"========================================\"\necho \"\"\n\n# ========================\n# Node.js 安装\n# ========================\ncheck_nodejs() {\n if command -v node &>/dev/null; then\n current_version=$(node -v | sed 's/v//')\n major_version=$(echo \"$current_version\" | cut -d. -f1)\n if [ \"$major_version\" -ge \"$NODE_MIN_VERSION\" ]; then\n log_success \"Node.js is already installed: v$current_version\"\n return 0\n fi\n log_info \"Node.js v$current_version < $NODE_MIN_VERSION, upgrading...\"\n fi\n\n log_info \"Installing Node.js...\"\n curl -fsSL https://deb.nodesource.com/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null || {\n curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_${NODE_INSTALL_VERSION}.x/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null\n }\n apt-get install -y nodejs 2>/dev/null || yum install -y nodejs 2>/dev/null\n log_success \"Node.js installed: $(node -v)\"\n log_success \"npm version: $(npm -v)\"\n}\n\n# ========================\n# Claude Code 安装\n# ========================\ninstall_claude_code() {\n if command -v claude &>/dev/null; then\n log_success \"Claude Code is already installed: $(claude --version 2>/dev/null || echo 'ok')\"\n else\n log_info \"Installing Claude Code...\"\n npm install -g \"$CLAUDE_PACKAGE\" 2>/dev/null || \\\n npm install -g \"$CLAUDE_PACKAGE\" --registry=https://registry.npmmirror.com\n log_success \"Claude Code installed successfully\"\n fi\n}\n\n# ========================\n# 跳过 Onboarding\n# ========================\nconfigure_claude_json() {\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude.json\");\n if (fs.existsSync(filePath)) {\n const content = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n fs.writeFileSync(filePath, JSON.stringify({ ...content, hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n } else {\n fs.writeFileSync(filePath, JSON.stringify({ hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n }\n '\n}\n\n# ========================\n# 写入 settings.json\n# ========================\nconfigure_claude() {\n log_info \"Configuring Claude Code...\"\n\n mkdir -p \"$HOME/.claude\"\n\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude\", \"settings.json\");\n const content = fs.existsSync(filePath)\n ? JSON.parse(fs.readFileSync(filePath, \"utf-8\"))\n : {};\n fs.writeFileSync(filePath, JSON.stringify({\n ...content,\n env: {\n ANTHROPIC_AUTH_TOKEN: \"'\"$API_KEY\"'\",\n ANTHROPIC_BASE_URL: \"'\"$PROVIDER_URL\"'\",\n ANTHROPIC_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_HAIKU_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_SONNET_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_OPUS_MODEL: \"'\"$MODEL\"'\",\n API_TIMEOUT_MS: \"'\"$API_TIMEOUT_MS\"'\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1\n }\n }, null, 2), \"utf-8\");\n ' || { log_error \"Failed to write settings.json\"; exit 1; }\n\n log_success \"Claude Code configured successfully\"\n}\n\n# ========================\n# 主流程\n# ========================\nmain() {\n check_nodejs\n install_claude_code\n configure_claude_json\n configure_claude\n\n echo \"\"\n log_success \"Installation completed successfully!\"\n echo \"\"\n echo \"🚀 使用方式: claude\"\n}\n\nmain \"$@\"\n"}, "08a75f45a1148ac0362ca9eb52f9bcc3e994a239": {"t": 1785764172.1483705, "n": 10964, "h": "963d8134b3b1d152", "c": "#!/bin/bash\n\n# Claude Code 容器内一键安装脚本\n# 用法: bash install_claude_code.sh [模型名称] [API_KEY] [BASE_URL]\n# 交互模式 (不传参): 先弹提供方菜单(智谱/百炼/幻方/火山/MiniMax/Kimi/阶跃/Anthropic/自定义),\n# 选完后填模型名(带默认) → 填 API_KEY, URL 由所选提供方自动给出\n# 非交互示例:\n# bash install_claude_code.sh glm-4.6 sk-xxx # 前缀自动匹配智谱\n# bash install_claude_code.sh glm-4.6 sk-xxx https://open.bigmodel.cn/api/anthropic\n# bash install_claude_code.sh Qwen3-30B-A3B \"\" http://localhost:8000/v1\n# bash install_claude_code.sh MiniMax-M1 sk-xxx # 前缀自动匹配 minimax\n# CLAUDE_PROVIDER=bailian bash install_claude_code.sh deepseek-v3 sk-xxx # 百炼托管的任意模型\n# CLAUDE_PROVIDER=moonshot bash install_claude_code.sh kimi-k2 sk-xxx\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型名前缀 > 交互菜单\n# CLAUDE_PROVIDER 取值: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\n# 适配\"一个 API 支持多种模型\"的平台 (百炼/火山/MiniMax 等), URL 与模型名无关时用它最稳\n# 仿照智谱官方脚本 https://cdn.bigmodel.cn/install/claude_code_env.sh\n\nset -euo pipefail\n\n# ========================\n# 常量定义\n# ========================\nNODE_MIN_VERSION=18\nNODE_INSTALL_VERSION=22\nCLAUDE_PACKAGE=\"@anthropic-ai/claude-code\"\nAPI_TIMEOUT_MS=3000000\n\n# ========================\n# 工具函数\n# ========================\nlog_info() { echo \"🔹 $*\"; }\nlog_success() { echo \"✅ $*\"; }\nlog_error() { echo \"❌ $*\" >&2; }\n\n# ========================\n# 参数解析\n# ========================\n# ========================\n# 平台清单 (展示名 | provider key | 默认模型 | Anthropic 兼容 URL)\n# ========================\nPROVIDER_NAMES=(\n \"智谱 AI (GLM)\"\n \"阿里百炼 (Qwen)\"\n \"幻方 DeepSeek\"\n \"火山方舟 (豆包)\"\n \"MiniMax (M1/abab)\"\n \"月之暗面 (Kimi)\"\n \"阶跃星辰 (Step)\"\n \"Anthropic 官方\"\n \"自定义 (手动填 URL)\"\n)\nPROVIDER_KEYS=( \"zhipu\" \"bailian\" \"deepseek\" \"volcano\" \"minimax\" \"moonshot\" \"stepfun\" \"anthropic\" \"custom\" )\nPROVIDER_MODELS=(\"glm-4.6\" \"qwen3-coder-plus\" \"deepseek-v3\" \"doubao-seed-1-6-250615\" \"MiniMax-M1\" \"kimi-k2\" \"step-2\" \"claude-sonnet-4-5\" \"\" )\nPROVIDER_URLS=(\n \"https://open.bigmodel.cn/api/anthropic\"\n \"https://dashscope.aliyuncs.com/apps/anthropic\"\n \"https://api.deepseek.com/anthropic\"\n \"https://ark.cn-beijing.volces.com/api/coding\"\n \"https://api.minimaxi.com/anthropic\"\n \"https://api.moonshot.cn/anthropic\"\n \"https://api.stepfun.com/step_plan\"\n \"https://api.anthropic.com\"\n \"\"\n)\n\n# ========================\n# 平台(provider) → Anthropic 兼容 URL\n# ========================\nurl_for_provider() {\n case \"$1\" in\n anthropic|claude) echo \"https://api.anthropic.com\" ;;\n zhipu|glm) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n deepseek) echo \"https://api.deepseek.com/anthropic\" ;;\n bailian|dashscope|qwen) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n volcano|ark|doubao) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n minimax) echo \"https://api.minimaxi.com/anthropic\" ;;\n moonshot|kimi) echo \"https://api.moonshot.cn/anthropic\" ;;\n stepfun|step) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 模型名前缀 → Anthropic 兼容 URL (无 provider 时的回退)\n# ========================\nget_provider_url() {\n local model=\"${1,,}\" # 小写化后匹配, 兼容 Qwen3 / GLM-4.6 等大写写法\n case \"$model\" in\n claude-*) echo \"https://api.anthropic.com\" ;;\n deepseek-*) echo \"https://api.deepseek.com/anthropic\" ;;\n glm-*|chatglm-*) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n doubao-*) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n qwen*|qwq*) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n minimax-*|MiniMax-*|abab*) echo \"https://api.minimaxi.com/anthropic\" ;;\n kimi-*|moonshot-*) echo \"https://api.moonshot.cn/anthropic\" ;;\n step-*) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 交互式选择提供方菜单\n# ========================\nselect_provider_menu() {\n echo \"请选择模型提供方:\"\n local i=1\n for name in \"${PROVIDER_NAMES[@]}\"; do\n printf \" [%d] %s\\n\" \"$i\" \"$name\"\n i=$((i+1))\n done\n echo \" [0] 退出\"\n echo \"\"\n local choice\n read -e -p \"请选择 [1-${#PROVIDER_NAMES[@]}]: \" choice\n if [ -z \"$choice\" ] || [ \"$choice\" = \"0\" ]; then\n log_error \"未选择提供方\"; exit 1\n fi\n if ! [[ \"$choice\" =~ ^[0-9]+$ ]] || [ \"$choice\" -lt 1 ] || [ \"$choice\" -gt \"${#PROVIDER_NAMES[@]}\" ]; then\n log_error \"无效选择: $choice\"; exit 1\n fi\n local idx=$((choice-1))\n SELECTED_KEY=\"${PROVIDER_KEYS[$idx]}\"\n SELECTED_MODEL=\"${PROVIDER_MODELS[$idx]}\"\n SELECTED_URL=\"${PROVIDER_URLS[$idx]}\"\n}\n\n# ========================\n# 参数与提供方选择\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型前缀 > 交互菜单\n# ========================\nCUSTOM_URL=\"${3:-}\"\nPROVIDER=\"${CLAUDE_PROVIDER:-}\"\nMODEL=\"${1:-}\"\nAPI_KEY=\"${2:-}\"\n\n# 交互模式 (未传模型名且未指定 provider/url): 先选提供方, 再填模型与 key\nif [ -z \"$MODEL\" ] && [ -z \"$CUSTOM_URL\" ] && [ -z \"$PROVIDER\" ]; then\n select_provider_menu\n PROVIDER=\"$SELECTED_KEY\"\n if [ \"$PROVIDER\" = \"custom\" ]; then\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n else\n PROVIDER_URL=\"$SELECTED_URL\"\n fi\n read -e -p \"请输入模型名称 (默认 ${SELECTED_MODEL}): \" MODEL\n MODEL=\"${MODEL:-$SELECTED_MODEL}\"\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\nelse\n # 非交互: 位置参数 + 环境变量\n [ -z \"$MODEL\" ] && { read -e -p \"请输入模型名称 (默认 deepseek-v4-pro): \" MODEL; MODEL=\"${MODEL:-deepseek-v4-pro}\"; }\n if [ -z \"$API_KEY\" ]; then\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\n fi\n if [ -n \"$CUSTOM_URL\" ]; then\n PROVIDER_URL=\"$CUSTOM_URL\"\n elif [ -n \"$PROVIDER\" ]; then\n PROVIDER_URL=$(url_for_provider \"$PROVIDER\")\n if [ -z \"$PROVIDER_URL\" ]; then\n log_error \"未知 CLAUDE_PROVIDER: $PROVIDER\"\n echo \"支持: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\" >&2\n exit 1\n fi\n else\n PROVIDER_URL=$(get_provider_url \"$MODEL\")\n fi\n if [ -z \"$PROVIDER_URL\" ]; then\n echo \"\"\n echo \"模型 '${MODEL}' 不在已知前缀列表中。\"\n echo \"可选: 1) 显式传 BASE_URL; 2) 设 CLAUDE_PROVIDER=<平台>; 3) 下方手动输入\"\n echo \"已知前缀: claude-*, deepseek-*, glm-*, doubao-*, qwen*, minimax-*, abab*, kimi-*, moonshot-*, step-*\"\n echo \"已知 provider: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\"\n echo \"\"\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n fi\nfi\n\necho \"\"\necho \"========================================\"\necho \" 模型: ${MODEL}\"\n[ -n \"$PROVIDER\" ] && echo \" 平台: ${PROVIDER}\"\necho \" API URL: ${PROVIDER_URL}\"\necho \" API_KEY: ${API_KEY}\"\necho \"========================================\"\necho \"\"\n\n# ========================\n# Node.js 安装\n# ========================\ncheck_nodejs() {\n if command -v node &>/dev/null; then\n current_version=$(node -v | sed 's/v//')\n major_version=$(echo \"$current_version\" | cut -d. -f1)\n if [ \"$major_version\" -ge \"$NODE_MIN_VERSION\" ]; then\n log_success \"Node.js is already installed: v$current_version\"\n return 0\n fi\n log_info \"Node.js v$current_version < $NODE_MIN_VERSION, upgrading...\"\n fi\n\n log_info \"Installing Node.js...\"\n curl -fsSL https://deb.nodesource.com/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null || {\n curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_${NODE_INSTALL_VERSION}.x/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null\n }\n apt-get install -y nodejs 2>/dev/null || yum install -y nodejs 2>/dev/null\n log_success \"Node.js installed: $(node -v)\"\n log_success \"npm version: $(npm -v)\"\n}\n\n# ========================\n# Claude Code 安装\n# ========================\ninstall_claude_code() {\n if command -v claude &>/dev/null; then\n log_success \"Claude Code is already installed: $(claude --version 2>/dev/null || echo 'ok')\"\n else\n log_info \"Installing Claude Code...\"\n npm install -g \"$CLAUDE_PACKAGE\" 2>/dev/null || \\\n npm install -g \"$CLAUDE_PACKAGE\" --registry=https://registry.npmmirror.com\n log_success \"Claude Code installed successfully\"\n fi\n}\n\n# ========================\n# 跳过 Onboarding\n# ========================\nconfigure_claude_json() {\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude.json\");\n if (fs.existsSync(filePath)) {\n const content = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n fs.writeFileSync(filePath, JSON.stringify({ ...content, hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n } else {\n fs.writeFileSync(filePath, JSON.stringify({ hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n }\n '\n}\n\n# ========================\n# 写入 settings.json\n# ========================\nconfigure_claude() {\n log_info \"Configuring Claude Code...\"\n\n mkdir -p \"$HOME/.claude\"\n\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude\", \"settings.json\");\n const content = fs.existsSync(filePath)\n ? JSON.parse(fs.readFileSync(filePath, \"utf-8\"))\n : {};\n fs.writeFileSync(filePath, JSON.stringify({\n ...content,\n env: {\n ANTHROPIC_AUTH_TOKEN: \"'\"$API_KEY\"'\",\n ANTHROPIC_BASE_URL: \"'\"$PROVIDER_URL\"'\",\n ANTHROPIC_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_HAIKU_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_SONNET_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_OPUS_MODEL: \"'\"$MODEL\"'\",\n API_TIMEOUT_MS: \"'\"$API_TIMEOUT_MS\"'\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1\n }\n }, null, 2), \"utf-8\");\n ' || { log_error \"Failed to write settings.json\"; exit 1; }\n\n log_success \"Claude Code configured successfully\"\n}\n\n# ========================\n# 主流程\n# ========================\nmain() {\n check_nodejs\n install_claude_code\n configure_claude_json\n configure_claude\n\n echo \"\"\n log_success \"Installation completed successfully!\"\n echo \"\"\n echo \"🚀 使用方式: claude\"\n}\n\nmain \"$@\"\n"}, "91e689a1bd0dcf818f61627e6ca78980c8b000c7": {"t": 1786067761.559076, "n": 10964, "h": "963d8134b3b1d152", "c": "#!/bin/bash\n\n# Claude Code 容器内一键安装脚本\n# 用法: bash install_claude_code.sh [模型名称] [API_KEY] [BASE_URL]\n# 交互模式 (不传参): 先弹提供方菜单(智谱/百炼/幻方/火山/MiniMax/Kimi/阶跃/Anthropic/自定义),\n# 选完后填模型名(带默认) → 填 API_KEY, URL 由所选提供方自动给出\n# 非交互示例:\n# bash install_claude_code.sh glm-4.6 sk-xxx # 前缀自动匹配智谱\n# bash install_claude_code.sh glm-4.6 sk-xxx https://open.bigmodel.cn/api/anthropic\n# bash install_claude_code.sh Qwen3-30B-A3B \"\" http://localhost:8000/v1\n# bash install_claude_code.sh MiniMax-M1 sk-xxx # 前缀自动匹配 minimax\n# CLAUDE_PROVIDER=bailian bash install_claude_code.sh deepseek-v3 sk-xxx # 百炼托管的任意模型\n# CLAUDE_PROVIDER=moonshot bash install_claude_code.sh kimi-k2 sk-xxx\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型名前缀 > 交互菜单\n# CLAUDE_PROVIDER 取值: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\n# 适配\"一个 API 支持多种模型\"的平台 (百炼/火山/MiniMax 等), URL 与模型名无关时用它最稳\n# 仿照智谱官方脚本 https://cdn.bigmodel.cn/install/claude_code_env.sh\n\nset -euo pipefail\n\n# ========================\n# 常量定义\n# ========================\nNODE_MIN_VERSION=18\nNODE_INSTALL_VERSION=22\nCLAUDE_PACKAGE=\"@anthropic-ai/claude-code\"\nAPI_TIMEOUT_MS=3000000\n\n# ========================\n# 工具函数\n# ========================\nlog_info() { echo \"🔹 $*\"; }\nlog_success() { echo \"✅ $*\"; }\nlog_error() { echo \"❌ $*\" >&2; }\n\n# ========================\n# 参数解析\n# ========================\n# ========================\n# 平台清单 (展示名 | provider key | 默认模型 | Anthropic 兼容 URL)\n# ========================\nPROVIDER_NAMES=(\n \"智谱 AI (GLM)\"\n \"阿里百炼 (Qwen)\"\n \"幻方 DeepSeek\"\n \"火山方舟 (豆包)\"\n \"MiniMax (M1/abab)\"\n \"月之暗面 (Kimi)\"\n \"阶跃星辰 (Step)\"\n \"Anthropic 官方\"\n \"自定义 (手动填 URL)\"\n)\nPROVIDER_KEYS=( \"zhipu\" \"bailian\" \"deepseek\" \"volcano\" \"minimax\" \"moonshot\" \"stepfun\" \"anthropic\" \"custom\" )\nPROVIDER_MODELS=(\"glm-4.6\" \"qwen3-coder-plus\" \"deepseek-v3\" \"doubao-seed-1-6-250615\" \"MiniMax-M1\" \"kimi-k2\" \"step-2\" \"claude-sonnet-4-5\" \"\" )\nPROVIDER_URLS=(\n \"https://open.bigmodel.cn/api/anthropic\"\n \"https://dashscope.aliyuncs.com/apps/anthropic\"\n \"https://api.deepseek.com/anthropic\"\n \"https://ark.cn-beijing.volces.com/api/coding\"\n \"https://api.minimaxi.com/anthropic\"\n \"https://api.moonshot.cn/anthropic\"\n \"https://api.stepfun.com/step_plan\"\n \"https://api.anthropic.com\"\n \"\"\n)\n\n# ========================\n# 平台(provider) → Anthropic 兼容 URL\n# ========================\nurl_for_provider() {\n case \"$1\" in\n anthropic|claude) echo \"https://api.anthropic.com\" ;;\n zhipu|glm) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n deepseek) echo \"https://api.deepseek.com/anthropic\" ;;\n bailian|dashscope|qwen) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n volcano|ark|doubao) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n minimax) echo \"https://api.minimaxi.com/anthropic\" ;;\n moonshot|kimi) echo \"https://api.moonshot.cn/anthropic\" ;;\n stepfun|step) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 模型名前缀 → Anthropic 兼容 URL (无 provider 时的回退)\n# ========================\nget_provider_url() {\n local model=\"${1,,}\" # 小写化后匹配, 兼容 Qwen3 / GLM-4.6 等大写写法\n case \"$model\" in\n claude-*) echo \"https://api.anthropic.com\" ;;\n deepseek-*) echo \"https://api.deepseek.com/anthropic\" ;;\n glm-*|chatglm-*) echo \"https://open.bigmodel.cn/api/anthropic\" ;;\n doubao-*) echo \"https://ark.cn-beijing.volces.com/api/coding\" ;;\n qwen*|qwq*) echo \"https://dashscope.aliyuncs.com/apps/anthropic\" ;;\n minimax-*|MiniMax-*|abab*) echo \"https://api.minimaxi.com/anthropic\" ;;\n kimi-*|moonshot-*) echo \"https://api.moonshot.cn/anthropic\" ;;\n step-*) echo \"https://api.stepfun.com/step_plan\" ;;\n *) echo \"\" ;;\n esac\n}\n\n# ========================\n# 交互式选择提供方菜单\n# ========================\nselect_provider_menu() {\n echo \"请选择模型提供方:\"\n local i=1\n for name in \"${PROVIDER_NAMES[@]}\"; do\n printf \" [%d] %s\\n\" \"$i\" \"$name\"\n i=$((i+1))\n done\n echo \" [0] 退出\"\n echo \"\"\n local choice\n read -e -p \"请选择 [1-${#PROVIDER_NAMES[@]}]: \" choice\n if [ -z \"$choice\" ] || [ \"$choice\" = \"0\" ]; then\n log_error \"未选择提供方\"; exit 1\n fi\n if ! [[ \"$choice\" =~ ^[0-9]+$ ]] || [ \"$choice\" -lt 1 ] || [ \"$choice\" -gt \"${#PROVIDER_NAMES[@]}\" ]; then\n log_error \"无效选择: $choice\"; exit 1\n fi\n local idx=$((choice-1))\n SELECTED_KEY=\"${PROVIDER_KEYS[$idx]}\"\n SELECTED_MODEL=\"${PROVIDER_MODELS[$idx]}\"\n SELECTED_URL=\"${PROVIDER_URLS[$idx]}\"\n}\n\n# ========================\n# 参数与提供方选择\n# URL 解析优先级: 显式 BASE_URL > CLAUDE_PROVIDER > 模型前缀 > 交互菜单\n# ========================\nCUSTOM_URL=\"${3:-}\"\nPROVIDER=\"${CLAUDE_PROVIDER:-}\"\nMODEL=\"${1:-}\"\nAPI_KEY=\"${2:-}\"\n\n# 交互模式 (未传模型名且未指定 provider/url): 先选提供方, 再填模型与 key\nif [ -z \"$MODEL\" ] && [ -z \"$CUSTOM_URL\" ] && [ -z \"$PROVIDER\" ]; then\n select_provider_menu\n PROVIDER=\"$SELECTED_KEY\"\n if [ \"$PROVIDER\" = \"custom\" ]; then\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n else\n PROVIDER_URL=\"$SELECTED_URL\"\n fi\n read -e -p \"请输入模型名称 (默认 ${SELECTED_MODEL}): \" MODEL\n MODEL=\"${MODEL:-$SELECTED_MODEL}\"\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\nelse\n # 非交互: 位置参数 + 环境变量\n [ -z \"$MODEL\" ] && { read -e -p \"请输入模型名称 (默认 deepseek-v4-pro): \" MODEL; MODEL=\"${MODEL:-deepseek-v4-pro}\"; }\n if [ -z \"$API_KEY\" ]; then\n read -e -p \"请输入 API_KEY (默认 sk-local): \" API_KEY\n API_KEY=\"${API_KEY:-sk-local}\"\n fi\n if [ -n \"$CUSTOM_URL\" ]; then\n PROVIDER_URL=\"$CUSTOM_URL\"\n elif [ -n \"$PROVIDER\" ]; then\n PROVIDER_URL=$(url_for_provider \"$PROVIDER\")\n if [ -z \"$PROVIDER_URL\" ]; then\n log_error \"未知 CLAUDE_PROVIDER: $PROVIDER\"\n echo \"支持: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\" >&2\n exit 1\n fi\n else\n PROVIDER_URL=$(get_provider_url \"$MODEL\")\n fi\n if [ -z \"$PROVIDER_URL\" ]; then\n echo \"\"\n echo \"模型 '${MODEL}' 不在已知前缀列表中。\"\n echo \"可选: 1) 显式传 BASE_URL; 2) 设 CLAUDE_PROVIDER=<平台>; 3) 下方手动输入\"\n echo \"已知前缀: claude-*, deepseek-*, glm-*, doubao-*, qwen*, minimax-*, abab*, kimi-*, moonshot-*, step-*\"\n echo \"已知 provider: anthropic zhipu deepseek bailian volcano minimax moonshot stepfun\"\n echo \"\"\n read -e -p \"请输入 API BASE_URL (如 http://192.168.1.100:8000/v1): \" PROVIDER_URL\n [ -z \"$PROVIDER_URL\" ] && { log_error \"API 地址不能为空\"; exit 1; }\n fi\nfi\n\necho \"\"\necho \"========================================\"\necho \" 模型: ${MODEL}\"\n[ -n \"$PROVIDER\" ] && echo \" 平台: ${PROVIDER}\"\necho \" API URL: ${PROVIDER_URL}\"\necho \" API_KEY: ${API_KEY}\"\necho \"========================================\"\necho \"\"\n\n# ========================\n# Node.js 安装\n# ========================\ncheck_nodejs() {\n if command -v node &>/dev/null; then\n current_version=$(node -v | sed 's/v//')\n major_version=$(echo \"$current_version\" | cut -d. -f1)\n if [ \"$major_version\" -ge \"$NODE_MIN_VERSION\" ]; then\n log_success \"Node.js is already installed: v$current_version\"\n return 0\n fi\n log_info \"Node.js v$current_version < $NODE_MIN_VERSION, upgrading...\"\n fi\n\n log_info \"Installing Node.js...\"\n curl -fsSL https://deb.nodesource.com/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null || {\n curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/nodesource/deb_${NODE_INSTALL_VERSION}.x/setup_${NODE_INSTALL_VERSION}.x | bash - 2>/dev/null\n }\n apt-get install -y nodejs 2>/dev/null || yum install -y nodejs 2>/dev/null\n log_success \"Node.js installed: $(node -v)\"\n log_success \"npm version: $(npm -v)\"\n}\n\n# ========================\n# Claude Code 安装\n# ========================\ninstall_claude_code() {\n if command -v claude &>/dev/null; then\n log_success \"Claude Code is already installed: $(claude --version 2>/dev/null || echo 'ok')\"\n else\n log_info \"Installing Claude Code...\"\n npm install -g \"$CLAUDE_PACKAGE\" 2>/dev/null || \\\n npm install -g \"$CLAUDE_PACKAGE\" --registry=https://registry.npmmirror.com\n log_success \"Claude Code installed successfully\"\n fi\n}\n\n# ========================\n# 跳过 Onboarding\n# ========================\nconfigure_claude_json() {\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude.json\");\n if (fs.existsSync(filePath)) {\n const content = JSON.parse(fs.readFileSync(filePath, \"utf-8\"));\n fs.writeFileSync(filePath, JSON.stringify({ ...content, hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n } else {\n fs.writeFileSync(filePath, JSON.stringify({ hasCompletedOnboarding: true }, null, 2), \"utf-8\");\n }\n '\n}\n\n# ========================\n# 写入 settings.json\n# ========================\nconfigure_claude() {\n log_info \"Configuring Claude Code...\"\n\n mkdir -p \"$HOME/.claude\"\n\n node --eval '\n const os = require(\"os\");\n const fs = require(\"fs\");\n const path = require(\"path\");\n const homeDir = os.homedir();\n const filePath = path.join(homeDir, \".claude\", \"settings.json\");\n const content = fs.existsSync(filePath)\n ? JSON.parse(fs.readFileSync(filePath, \"utf-8\"))\n : {};\n fs.writeFileSync(filePath, JSON.stringify({\n ...content,\n env: {\n ANTHROPIC_AUTH_TOKEN: \"'\"$API_KEY\"'\",\n ANTHROPIC_BASE_URL: \"'\"$PROVIDER_URL\"'\",\n ANTHROPIC_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_HAIKU_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_SONNET_MODEL: \"'\"$MODEL\"'\",\n ANTHROPIC_DEFAULT_OPUS_MODEL: \"'\"$MODEL\"'\",\n API_TIMEOUT_MS: \"'\"$API_TIMEOUT_MS\"'\",\n CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: 1\n }\n }, null, 2), \"utf-8\");\n ' || { log_error \"Failed to write settings.json\"; exit 1; }\n\n log_success \"Claude Code configured successfully\"\n}\n\n# ========================\n# 主流程\n# ========================\nmain() {\n check_nodejs\n install_claude_code\n configure_claude_json\n configure_claude\n\n echo \"\"\n log_success \"Installation completed successfully!\"\n echo \"\"\n echo \"🚀 使用方式: claude\"\n}\n\nmain \"$@\"\n"}}}}