配置: 同步模板文件至多 Provider 架构并添加 .env 模板
CI / lint (push) Successful in 7s

This commit is contained in:
2026-04-30 16:23:40 +08:00
parent 7eb22db481
commit 3a37b9cb2a
5 changed files with 176 additions and 26 deletions
+13
View File
@@ -257,6 +257,19 @@ if [ ! -f "$RUNCC_SCRIPT" ]; then
echo " $(status_ok) 已从模板创建 runcc.sh"
fi
# 检查并创建 .env(从示例模板复制)
ENV_FILE="$WORKSPACE/.devcontainer/.volumes/bin/.env"
ENV_TEMPLATE="$SCRIPT_DIR/templates/.env.example"
if [ ! -f "$ENV_FILE" ] && [ -f "$ENV_TEMPLATE" ]; then
# 如果有 API_KEY,替换 GLM 占位符
if [ -n "${API_KEY:-}" ]; then
sed "s/{{your_glm_api_key}}/$API_KEY/g" "$ENV_TEMPLATE" > "$ENV_FILE"
else
cp "$ENV_TEMPLATE" "$ENV_FILE"
fi
echo " $(status_ok) 已从模板创建 .env(请编辑配置凭据)"
fi
# 配置 Open Code
echo "配置 Open Code..."
if [ -f "$WORKSPACE/.devcontainer/opencode.json.example" ]; then
+36
View File
@@ -0,0 +1,36 @@
# ── Provider 选择 ────────────────────────────────────────
# 变量命名规则: <PROVIDER>_BASE_URL, <PROVIDER>_AUTH_TOKEN, <PROVIDER>_DEFAULT_MODEL, <PROVIDER>_CONTEXT_WINDOW
# 例如 CC_PROVIDER=glm → 读取 GLM_BASE_URL, GLM_AUTH_TOKEN, GLM_DEFAULT_MODEL, GLM_CONTEXT_WINDOW
CC_PROVIDER=glm
# ── Claude Code 路径配置 ──────────────────────────────────
# settings.json 路径(用于清理残留的旧配置)
SETTINGS_FILE=$HOME/.claude/settings.json
# ── GLM Coding Plan (open.bigmodel.cn) ──────────────────
GLM_BASE_URL=https://open.bigmodel.cn/api/anthropic
GLM_AUTH_TOKEN={{your_glm_api_key}}
GLM_DEFAULT_MODEL=51
GLM_CONTEXT_WINDOW=200000
GLM_COMPACT_PCT=75
# ── DeepSeek (api.deepseek.com) ─────────────────────────
# 取消注释以下行以启用 DeepSeek:
# DEEPSEEK_BASE_URL=https://api.deepseek.com/anthropic
# DEEPSEEK_AUTH_TOKEN={{your_deepseek_api_key}}
# DEEPSEEK_DEFAULT_MODEL=ds
# DEEPSEEK_CONTEXT_WINDOW=1000000
# DEEPSEEK_COMPACT_PCT=50
# DEEPSEEK_DISABLE_COMPACT=1
# DEEPSEEK_MAX_CONTEXT_TOKENS=1000000
# ── 添加新 Provider ──────────────────────────────────────
# 按以下格式添加即可,无需修改 runcc.sh:
# MYPROVIDER_BASE_URL=https://api.example.com/anthropic
# MYPROVIDER_AUTH_TOKEN=your-token
# MYPROVIDER_DEFAULT_MODEL=model-name
# MYPROVIDER_CONTEXT_WINDOW=200000
# MYPROVIDER_COMPACT_PCT=75
# MYPROVIDER_DISABLE_COMPACT=1 # 可选:禁用自动压缩(API 报告值 < 实际值时使用)
# MYPROVIDER_MAX_CONTEXT_TOKENS=1000000 # 可选:覆盖 Claude Code 的上下文窗口假设
# 然后设置 CC_PROVIDER=myprovider 即可使用
+4
View File
@@ -63,6 +63,10 @@ alias cc5='cc 5'
alias cc5t='cc 5t'
alias cc51='cc 51'
# DeepSeek 快捷方式
alias ccds='cc -p deepseek ds'
alias ccdsf='cc -p deepseek dsf'
# tmux pane 级模型继承:从 pane option 读取模型配置(由 runcc.sh 写入)
# 覆盖 session 级环境变量,实现同 session 不同 pane 的模型隔离
if [ -n "${TMUX:-}" ]; then
+118 -26
View File
@@ -1,14 +1,37 @@
#!/bin/bash
# Claude Code 启动脚本,支持通过参数选择 GLM 模型版本
# Claude Code 启动脚本
# 支持多 Provider (通过 .env 配置,自动解析 ${PROVIDER}_BASE_URL / ${PROVIDER}_AUTH_TOKEN)
#
# 固定版本: 2.1.112 (来自 /workspace/.devcontainer/.cache/npm/anthropic-ai-claude-code-2.1.112.tgz)
# 注意: 不再执行自动更新,以保持版本稳定
SETTINGS_FILE="/workspace/.devcontainer/.volumes/claude/settings.json"
# ── 路径配置 ──────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="${SCRIPT_DIR}/.env"
# 参数解析: runcc.sh [--name <名称>] [模型]
# ── 加载 .env 文件 ──────────────────────────────────────
if [ -f "$ENV_FILE" ]; then
while IFS= read -r line || [ -n "$line" ]; do
# 跳过注释和空行
[[ "$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "${line// /}" ]] && continue
# 解析 key=value
key="${line%%=*}"
value="${line#*=}"
# 去除引号
[[ "$value" =~ ^\"(.*)\"$ ]] && value="${BASH_REMATCH[1]}"
[[ "$value" =~ ^\'(.*)\'$ ]] && value="${BASH_REMATCH[1]}"
# 仅导出合法变量名
if [[ "$key" =~ ^[a-zA-Z_][a-zA-Z0-9_]*$ ]]; then
export "$key=$value"
fi
done < "$ENV_FILE"
fi
# ── 参数解析 ──────────────────────────────────────────────
SESSION_NAME=""
MODEL_KEY=""
PROVIDER_OVERRIDE=""
while [ $# -gt 0 ]; do
case "$1" in
@@ -16,13 +39,29 @@ while [ $# -gt 0 ]; do
[ $# -ge 2 ] || { echo "错误: --name 需要参数" >&2; exit 1; }
SESSION_NAME="$2"; shift 2
;;
--provider|-p)
[ $# -ge 2 ] || { echo "错误: --provider 需要参数" >&2; exit 1; }
PROVIDER_OVERRIDE="$2"; shift 2
;;
-h|--help)
echo "用法: runcc.sh [--name <名称>] [模型]"
echo "用法: runcc.sh [选项] [模型]"
echo ""
echo "选项:"
echo " --name, -n <名称> Claude Code 会话显示名称"
echo " --name, -n <名称> Claude Code 会话显示名称"
echo " --provider, -p <名称> API 提供商 (由 .env 配置,如 glm / deepseek)"
echo ""
echo "模型: 45|45a|46|47|5|5t|51 (默认 51)"
echo "GLM 模型: 45|45a|46|47|5|5t|51"
echo "DeepSeek 模型: ds|dsf"
echo "其他: 直接传入模型名称"
echo ""
echo "Provider 变量规则: CC_PROVIDER=<name> → <NAME>_BASE_URL + <NAME>_AUTH_TOKEN"
echo " 添加新 Provider 只需在 .env 中按此格式添加变量即可"
echo ""
echo "示例:"
echo " runcc.sh # 默认 Provider + 默认模型"
echo " runcc.sh 47 # 默认 Provider + glm-4.7"
echo " runcc.sh --provider deepseek # DeepSeek + 默认模型"
echo " runcc.sh -p deepseek dsf # DeepSeek + deepseek-v4-flash"
exit 0
;;
*)
@@ -31,8 +70,61 @@ while [ $# -gt 0 ]; do
esac
done
MODEL_KEY="${MODEL_KEY:-51}" # 默认使用 glm-5.1
# ── Provider 动态解析 ─────────────────────────────────────
# CC_PROVIDER=glm → GLM_BASE_URL, GLM_AUTH_TOKEN, GLM_DEFAULT_MODEL
# CC_PROVIDER=deepseek → DEEPSEEK_BASE_URL, DEEPSEEK_AUTH_TOKEN, DEEPSEEK_DEFAULT_MODEL
# CC_PROVIDER=xxx → XXX_BASE_URL, XXX_AUTH_TOKEN, XXX_DEFAULT_MODEL, XXX_CONTEXT_WINDOW
CC_PROVIDER="${PROVIDER_OVERRIDE:-${CC_PROVIDER:-glm}}"
upper_provider="$(echo "$CC_PROVIDER" | tr '[:lower:]' '[:upper:]')"
base_url_var="${upper_provider}_BASE_URL"
token_var="${upper_provider}_AUTH_TOKEN"
default_model_var="${upper_provider}_DEFAULT_MODEL"
context_window_var="${upper_provider}_CONTEXT_WINDOW"
compact_pct_var="${upper_provider}_COMPACT_PCT"
disable_compact_var="${upper_provider}_DISABLE_COMPACT"
max_ctx_var="${upper_provider}_MAX_CONTEXT_TOKENS"
ANTHROPIC_BASE_URL="${!base_url_var}"
ANTHROPIC_AUTH_TOKEN="${!token_var}"
DEFAULT_MODEL="${!default_model_var:-}"
CONTEXT_WINDOW="${!context_window_var:-200000}"
COMPACT_PCT="${!compact_pct_var:-75}"
DISABLE_COMPACT="${!disable_compact_var:-}"
MAX_CONTEXT_TOKENS="${!max_ctx_var:-}"
if [ -z "$ANTHROPIC_BASE_URL" ] || [ -z "$ANTHROPIC_AUTH_TOKEN" ]; then
echo "错误: Provider '$CC_PROVIDER' 未配置 BASE_URL 或 AUTH_TOKEN" >&2
echo "请在 ${ENV_FILE} 中添加: ${upper_provider}_BASE_URL, ${upper_provider}_AUTH_TOKEN" >&2
exit 1
fi
export ANTHROPIC_BASE_URL ANTHROPIC_AUTH_TOKEN
export CC_CONTEXT_WINDOW="$CONTEXT_WINDOW"
# DISABLE_COMPACT 模式: 禁用自动压缩,覆盖上下文窗口(适用于 API 报告值 < 实际值的模型)
if [ "$DISABLE_COMPACT" = "1" ]; then
export DISABLE_COMPACT=1
export CLAUDE_CODE_MAX_CONTEXT_TOKENS="${MAX_CONTEXT_TOKENS:-$CONTEXT_WINDOW}"
else
export CLAUDE_AUTOCOMPACT_PCT_OVERRIDE="$COMPACT_PCT"
fi
# ── 更新 settings.json ──────────────────────────────────
# 删除凭据、模型和窗口变量(由环境变量接管)
# SETTINGS_FILE 路径由 .env 配置,默认 ~/.claude/settings.json
SETTINGS_FILE="${SETTINGS_FILE:-$HOME/.claude/settings.json}"
if command -v jq &>/dev/null && [ -f "$SETTINGS_FILE" ]; then
jq 'del(.env.ANTHROPIC_BASE_URL, .env.ANTHROPIC_AUTH_TOKEN, .env.CLAUDE_CODE_AUTO_COMPACT_WINDOW, .env.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE, .env.DISABLE_COMPACT, .env.CLAUDE_CODE_MAX_CONTEXT_TOKENS, .env.ANTHROPIC_DEFAULT_OPUS_MODEL, .env.ANTHROPIC_DEFAULT_HAIKU_MODEL, .env.ANTHROPIC_DEFAULT_SONNET_MODEL)' \
"$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" \
&& mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
fi
# ── 模型解析 ──────────────────────────────────────────────
MODEL_KEY="${MODEL_KEY:-$DEFAULT_MODEL}"
case "$MODEL_KEY" in
# GLM 系列
45) MODEL="glm-4.5" ;;
45a) MODEL="glm-4.5-air" ;;
46) MODEL="glm-4.6" ;;
@@ -40,19 +132,13 @@ case "$MODEL_KEY" in
5) MODEL="glm-5" ;;
5t) MODEL="glm-5-turbo" ;;
51) MODEL="glm-5.1" ;;
*)
echo "未知模型: $MODEL_KEY (可选: 45|45a|46|47|5|5t|51)"
exit 1
;;
# DeepSeek 系列
ds) MODEL="deepseek-v4-pro" ;;
dsf) MODEL="deepseek-v4-flash" ;;
# 其他: 直接作为模型名称
*) MODEL="$MODEL_KEY" ;;
esac
# 从 settings.json 中移除模型相关配置(避免覆盖 shell 环境变量)
if command -v jq &>/dev/null && [ -f "$SETTINGS_FILE" ]; then
jq 'del(.env.ANTHROPIC_DEFAULT_OPUS_MODEL, .env.ANTHROPIC_DEFAULT_HAIKU_MODEL, .env.ANTHROPIC_DEFAULT_SONNET_MODEL)' \
"$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" \
&& mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
fi
# ── 模型环境变量(三个层级统一为同一模型)────────────────
export ANTHROPIC_DEFAULT_HAIKU_MODEL="$MODEL"
export ANTHROPIC_DEFAULT_SONNET_MODEL="$MODEL"
@@ -62,24 +148,30 @@ export ANTHROPIC_DEFAULT_OPUS_MODEL="$MODEL"
if [ -n "${TMUX:-}" ]; then
SESSION_ID="$(tmux display-message -p '#{session_id}')"
# 层级 2: session 级环境变量(不同 session 隔离)
tmux setenv -t "$SESSION_ID" ANTHROPIC_DEFAULT_OPUS_MODEL "$MODEL"
tmux setenv -t "$SESSION_ID" ANTHROPIC_DEFAULT_HAIKU_MODEL "$MODEL"
tmux setenv -t "$SESSION_ID" ANTHROPIC_DEFAULT_SONNET_MODEL "$MODEL"
tmux setenv -t "$SESSION_ID" CC_CONTEXT_WINDOW "$CONTEXT_WINDOW"
if [ "$DISABLE_COMPACT" = "1" ]; then
tmux setenv -t "$SESSION_ID" DISABLE_COMPACT 1
tmux setenv -t "$SESSION_ID" CLAUDE_CODE_MAX_CONTEXT_TOKENS "${MAX_CONTEXT_TOKENS:-$CONTEXT_WINDOW}"
tmux setenv -u -t "$SESSION_ID" CLAUDE_AUTOCOMPACT_PCT_OVERRIDE 2>/dev/null || true
else
tmux setenv -t "$SESSION_ID" CLAUDE_AUTOCOMPACT_PCT_OVERRIDE "$COMPACT_PCT"
tmux setenv -u -t "$SESSION_ID" DISABLE_COMPACT 2>/dev/null || true
tmux setenv -u -t "$SESSION_ID" CLAUDE_CODE_MAX_CONTEXT_TOKENS 2>/dev/null || true
fi
# 层级 3: pane 级选项(同 session 不同 pane 隔离)
# .bashrc 会在新 shell 启动时读取此选项,覆盖 session 级设置
tmux set-option -p @anthropic_model "$MODEL"
fi
# 构建启动参数
CC_ARGS=(--ide --dangerously-skip-permissions --allow-dangerously-skip-permissions)
# ── 启动 Claude Code ────────────────────────────────────
CC_ARGS=(--ide --dangerously-skip-permissions --allow-dangerously-skip-permissions --effort max)
# --name 不可靠(不写 custom-title/agent-name JSONL 记录),
# 改用 /rename 斜杠命令作为初始提示,确保名称正确持久化
if [ -n "$SESSION_NAME" ]; then
INITIAL_PROMPT="/rename $SESSION_NAME"
fi
echo "启动 Claude Code (模型: $MODEL${SESSION_NAME:+, 会话: $SESSION_NAME})"
echo "启动 Claude Code (provider: $CC_PROVIDER, 模型: $MODEL${SESSION_NAME:+, 会话: $SESSION_NAME})"
claude "${CC_ARGS[@]}" ${INITIAL_PROMPT:+"$INITIAL_PROMPT"}
+5
View File
@@ -116,3 +116,8 @@ runcc.sh 中 SETTINGS_FILE 变量是否会造成影响?
使用 tmux 分别对 runcc.sh , runcc.sh -p deepseek 进行测试, 看是否符合修改要求.
## 2026-04-30 16:16:16
更新 @.devcontainer/templates/ 目录下相关文件.