#!/usr/bin/env bash # tokenfunc 一键配置脚本(macOS / Linux)。由站点按请求生成,站点地址已填好。 # 用法:curl -fsSL <站点地址>/install/<工具>.sh | bash # 可选环境变量: # TOKENFUNC_API_KEY 跳过密钥输入(适合自动化) # TOKENFUNC_MODEL 指定默认模型,跳过模型选择 # TOKENFUNC_SKIP_INSTALL 设为 1 时不自动安装工具,只写配置 set -euo pipefail TF_BASE_URL="https://tokenfunc.com" TF_SITE_NAME="tokenfunc" tf_info() { printf '\033[32m==>\033[0m %s\n' "$*"; } tf_warn() { printf '\033[33m[!]\033[0m %s\n' "$*" >&2; } tf_die() { printf '\033[31m[x]\033[0m %s\n' "$*" >&2 exit 1 } tf_have() { command -v "$1" >/dev/null 2>&1; } # 脚本通过管道运行时 stdin 是脚本本身,交互输入必须从终端读 tf_has_tty() { [ -r /dev/tty ] && [ -w /dev/tty ] && : 2>/dev/null /dev/tty IFS= read -rs TF_KEY /dev/tty TF_KEY="$(printf '%s' "$TF_KEY" | tr -d '[:space:]')" [ -n "$TF_KEY" ] || tf_die "密钥不能为空。可在 $TF_BASE_URL/keys 创建或复制密钥" } # 用 /v1/models 校验地址与密钥(不扣费),同时拿到这把密钥可用的模型 tf_fetch_models() { tf_have curl || tf_die "需要 curl" local response status body response="$(curl -sS --max-time 20 -w '\n%{http_code}' \ -H "Authorization: Bearer $TF_KEY" "$TF_BASE_URL/v1/models")" || tf_die "无法连接 $TF_BASE_URL,请检查网络或代理" status="${response##*$'\n'}" body="${response%$'\n'*}" case "$status" in 200) ;; 401 | 403) tf_die "密钥无效或已停用(HTTP $status),请到 $TF_BASE_URL/keys 检查" ;; *) tf_die "校验密钥失败(HTTP $status)" ;; esac TF_MODELS="$(printf '%s' "$body" | grep -o '"id": *"[^"]*"' | sed 's/^"id": *"//; s/"$//' || true)" tf_info "密钥有效" } # 选默认模型:$1 为优先匹配的正则,$2 为提示里的系列名 tf_choose_model() { if [ -n "${TOKENFUNC_MODEL:-}" ]; then TF_MODEL="$TOKENFUNC_MODEL" return fi local candidates count choice candidates="$(printf '%s\n' "$TF_MODELS" | grep -Ei "$1" || true)" [ -n "$candidates" ] || candidates="$TF_MODELS" [ -n "$candidates" ] || tf_die "这把密钥没有可用的模型,请检查密钥分组或联系管理员" count="$(printf '%s\n' "$candidates" | wc -l | tr -d ' ')" if [ "$count" = 1 ] || ! tf_has_tty; then TF_MODEL="$(printf '%s\n' "$candidates" | head -n 1)" tf_info "默认模型:$TF_MODEL" return fi printf '\n可用的%s模型:\n' "$2" >/dev/tty printf '%s\n' "$candidates" | head -n 30 | awk '{ printf " %2d. %s\n", NR, $0 }' >/dev/tty printf '选择默认模型(输入序号或模型名,直接回车选 1):' >/dev/tty IFS= read -r choice "$tmp" mv "$tmp" "$file" tf_info "已写入 $file" } # 把 TOKENFUNC_API_KEY 写进当前 shell 的启动文件,新开终端即生效 tf_persist_key() { local shell_name rc line tmp shell_name="$(basename "${SHELL:-}")" case "$shell_name" in zsh) rc="$HOME/.zshrc" ;; bash) if [ "$(uname -s)" = Darwin ]; then rc="$HOME/.bash_profile"; else rc="$HOME/.bashrc"; fi ;; fish) rc="$HOME/.config/fish/config.fish" ;; *) rc="$HOME/.profile" ;; esac if [ "$shell_name" = fish ]; then line="set -gx TOKENFUNC_API_KEY \"$TF_KEY\"" else line="export TOKENFUNC_API_KEY=\"$TF_KEY\"" fi mkdir -p "$(dirname "$rc")" touch "$rc" tmp="$(mktemp)" grep -v -E '^[[:space:]]*(export[[:space:]]+TOKENFUNC_API_KEY=|set -gx TOKENFUNC_API_KEY )' "$rc" >"$tmp" || true printf '%s\n' "$line" >>"$tmp" cat "$tmp" >"$rc" rm -f "$tmp" tf_info "已把 TOKENFUNC_API_KEY 写入 $rc" } tf_info "$TF_SITE_NAME · Codex 一键配置" tf_read_key tf_fetch_models tf_choose_model 'gpt|codex' ' GPT ' tf_ensure_tool codex 'curl -fsSL https://chatgpt.com/codex/install.sh | sh' '@openai/codex' tf_write_codex_config tf_persist_key printf '\n' tf_info "配置完成:地址 $TF_BASE_URL/v1,默认模型 $TF_MODEL" tf_info "请新开一个终端再运行 codex(密钥环境变量在新终端才生效),输入 /status 确认 provider 为 tokenfunc"