#!/usr/bin/env python3 from __future__ import annotations import argparse import json import shutil import sqlite3 import sys import time from pathlib import Path TOOLS = { "codex": ("Codex", "codex"), "opencode": ("OpenCode", "codex"), "openclaw": ("OpenClaw", "codex"), "claude": ("Claude Code", "claude"), } MODELS = ["gpt-5.5", "gpt-5.4", "gpt-5.3-codex", "gpt-5.2", "gpt-5.4-mini"] def codex_config(api_key: str, model: str, label: str) -> dict: provider = "aitoken666" config = f"""model_provider = "{provider}" model = "{model}" model_reasoning_effort = "high" disable_response_storage = true [model_providers.{provider}] name = "AI Token 666" base_url = "https://aitoken666.asia/v1" wire_api = "responses" requires_openai_auth = true """ return { "app_type": "codex", "settings": {"auth": {"OPENAI_API_KEY": api_key}, "config": config}, "notes": f"AI Token 666 for {label}", } def claude_config(api_key: str, model: str, label: str) -> dict: return { "app_type": "claude", "settings": { "env": { "ANTHROPIC_AUTH_TOKEN": api_key, "ANTHROPIC_BASE_URL": "https://aitoken666.asia", "ANTHROPIC_MODEL": model, } }, "notes": f"AI Token 666 for {label}", } def build_config(tool: str, api_key: str, model: str) -> tuple[str, str, str, dict]: label, _ = TOOLS[tool] data = claude_config(api_key, model, label) if tool == "claude" else codex_config(api_key, model, label) provider_id = f"aitoken666-{tool}" provider_name = f"AI Token 666 - {label}" return provider_id, provider_name, data["app_type"], data def show_window() -> dict | None: try: import tkinter as tk from tkinter import messagebox, ttk except Exception: return None result: dict = {} root = tk.Tk() root.title("AI Token 666 导入 CC Switch") root.geometry("520x330") root.resizable(False, False) pad = {"padx": 18, "pady": 8} ttk.Label(root, text="选择要配置的编程工具").pack(anchor="w", **pad) tool_var = tk.StringVar(value="codex") tool_box = ttk.Combobox(root, textvariable=tool_var, state="readonly", values=list(TOOLS.keys())) tool_box.pack(fill="x", padx=18) ttk.Label(root, text="选择模型").pack(anchor="w", **pad) model_var = tk.StringVar(value="gpt-5.5") model_box = ttk.Combobox(root, textvariable=model_var, values=MODELS) model_box.pack(fill="x", padx=18) ttk.Label(root, text="粘贴你在 AI Token 666 后台创建的 API Key").pack(anchor="w", **pad) key_var = tk.StringVar() key_entry = ttk.Entry(root, textvariable=key_var, show="*", width=64) key_entry.pack(fill="x", padx=18) key_entry.focus_set() ttk.Label( root, text="提示:推荐先选 Codex。OpenCode / OpenClaw 使用 OpenAI-compatible 配置。", foreground="#666666", wraplength=470, ).pack(anchor="w", padx=18, pady=(8, 4)) def submit() -> None: api_key = key_var.get().strip() model = model_var.get().strip() tool = tool_var.get().strip() if not api_key.startswith("sk-"): messagebox.showerror("API Key 不正确", "API Key 应以 sk- 开头,请检查是否复制完整。") return if not model: messagebox.showerror("模型不能为空", "请选择或填写一个模型名。") return result.update({"api_key": api_key, "model": model, "tool": tool}) root.destroy() ttk.Button(root, text="确认导入到 CC Switch", command=submit).pack(fill="x", padx=18, pady=18) root.mainloop() return result or None def import_provider(api_key: str, model: str, tool: str) -> Path: db = Path.home() / ".cc-switch" / "cc-switch.db" if not db.exists(): raise SystemExit(f"未找到 CC Switch 数据库:{db}\n请先安装并运行一次 CC Switch。") backup = db.with_name(f"cc-switch.before-aitoken666-{int(time.time())}.db") shutil.copy2(db, backup) provider_id, provider_name, app_type, data = build_config(tool, api_key, model) settings = json.dumps(data["settings"], ensure_ascii=False) meta = json.dumps({"commonConfigEnabled": False, "endpointAutoSelect": True}, ensure_ascii=False) now = int(time.time() * 1000) con = sqlite3.connect(db) try: con.execute("delete from providers where id=? and app_type=?", (provider_id, app_type)) con.execute( "insert into providers (id, app_type, name, settings_config, website_url, category, created_at, sort_index, notes, icon, icon_color, meta, is_current, in_failover_queue, cost_multiplier, provider_type) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", ( provider_id, app_type, provider_name, settings, "https://aitoken666.asia", "custom", now, now, data["notes"], None, None, meta, 0, 0, "1.0", None, ), ) con.commit() finally: con.close() return backup def main() -> int: parser = argparse.ArgumentParser(description="Import AI Token 666 into CC Switch.") parser.add_argument("--api-key", help="Your sk- API key from aitoken666.asia") parser.add_argument("--model", default="gpt-5.5") parser.add_argument("--tool", choices=sorted(TOOLS), default="codex") args = parser.parse_args() if not args.api_key: chosen = show_window() if chosen: args.api_key = chosen["api_key"] args.model = chosen["model"] args.tool = chosen["tool"] else: parser.error("缺少 --api-key,且无法打开图形窗口。") if not args.api_key.startswith("sk-"): raise SystemExit("API Key 看起来不对:应以 sk- 开头。") backup = import_provider(args.api_key, args.model, args.tool) print("导入完成:AI Token 666 已添加到 CC Switch。") print(f"工具:{TOOLS[args.tool][0]}") print(f"模型:{args.model}") print(f"已备份原数据库:{backup}") print("请重新打开 CC Switch,选择并启用 AI Token 666。") return 0 if __name__ == "__main__": raise SystemExit(main())