import os import sqlite3 import uuid import datetime # 1. 定位原项目在 Docker 容器内生成的 SQLite 数据库路径 # 原项目默认存放在 server/prisma/dev.db 或类似路径下,根据容器内实际路径做安全兼容 DB_PATHS = [ "/app/server/prisma/dev.db", "server/prisma/dev.db", "prisma/dev.db" ] def get_active_db(): for path in DB_PATHS: if os.path.exists(path): return path # 如果还没生成,尝试初始化一个路径 return "/app/server/prisma/dev.db" def inject_secrets_to_sqlite(): db_path = get_active_db() print(f"📦 正在连接 FreeLLMAPI 核心数据库: {db_path}") # 对齐你配置的 HF Secrets 名字与项目数据库里的 Provider 标识 secrets_map = { "GOOGLE_API_KEY": "google", "GROQ_API_KEY": "groq", "GITHUB_TOKEN": "github", "OPENROUTER_API_KEY": "openrouter", "MISTRAL_API_KEY": "mistral", "TOGETHER_API_KEY": "together", "NVIDIA_API_KEY": "nvidia", "COHERE_API_KEY": "cohere", "HF_TOKEN": "huggingface", "CEREBRAS_API_KEY": "cerebras", "SAMBANOVA_API_KEY": "sambanova", "CLOUDFLARE_API_TOKEN": "cloudflare", "ZHIPU_API_KEY": "zhipu" } try: conn = sqlite3.connect(db_path) cursor = conn.cursor() # 2. 检查原项目内 Provider 或者是 Keys 表的结构 # 原项目的表名通常叫 Provider 或者 Credentials cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables = [t[0] for t in cursor.fetchall()] print(f"📊 探测到系统当前表结构: {tables}") # 寻找存储渠道的表(通常包含 'Provider' 或 'Credential' 关键字) target_table = "Provider" if "Provider" in tables else None if not target_table: for t in tables: if "key" in t.lower() or "provider" in t.lower(): target_table = t break if not target_table: print("❌ 未能识别到原项目的密钥存储表,请先在前端随便手动添加任意一个Key以初始化数据库。") return # 3. 遍历并强行注入 Secrets success_count = 0 now = datetime.datetime.utcnow().isoformat() for secret_name, provider_id in secrets_map.items(): actual_key = os.getenv(secret_name) if not actual_key: continue # 检查数据库中是否已存在该渠道,防止重复插入 cursor.execute(f"SELECT id FROM {target_table} WHERE name = ? OR provider = ?", (provider_id, provider_id)) exists = cursor.fetchone() if not exists: # 动态生成符合 Prisma 规范的记录 # 💡 注意:原版采用了不加密或自加密,这里直接存入(如果原版带加密,脚本运行后前端会显示加密格式) record_id = str(uuid.uuid4()) try: # 根据标准的 Prisma 字段结构进行弹性插入 cursor.execute(f""" INSERT INTO {target_table} (id, name, provider, apiKey, status, createdAt, updatedAt) VALUES (?, ?, ?, ?, ?, ?, ?) """, (record_id, provider_id, provider_id, actual_key, "active", now, now)) success_count += 1 except sqlite3.OperationalError: # 如果字段不完全对齐,尝试最简化插入 cursor.execute(f""" INSERT INTO {target_table} (id, name, apiKey) VALUES (?, ?, ?) """, (record_id, provider_id, actual_key)) success_count += 1 conn.commit() conn.close() print(f"🏁 注入成功!已将 {success_count} 个云端 Secrets 强制同步到本地 SQLite。") except Exception as e: print(f"⚠️ 自动注入过程中发生意外,正在等待系统原生初始化: {str(e)}") if __name__ == "__main__": inject_secrets_to_sqlite()