# dsfree2api 示例配置。 # 复制为 config.toml 后按需修改;运行 `dsfree2api -check -config config.toml` 可校验。 # 环境变量优先级高于本文件:HOST PORT LOG_LEVEL LOG_FILE API_KEYS PROXY_URL PROXY_FALLBACK_URLS # PROXY_SLOW_START_SECONDS TURNSTILE_ENABLED TURNSTILE_API_KEY TURNSTILE_PROVIDER # TURNSTILE_BROWSER_PATH TURNSTILE_TIMEOUT_SECONDS TURNSTILE_WARM_ENABLED # TURNSTILE_WARM_RATIO TURNSTILE_WARM_CHECK_SECONDS # ADMIN_ENABLED ADMIN_HOST ADMIN_PORT ADMIN_PASSWORD DATA_DIR [server] host = "0.0.0.0" port = 8000 log_level = "INFO" # 日志文件:留空写入 /logs/dsfree2api.log;填路径则写到该文件; # "-" = 仅终端。日志按天轮转,旧文件压缩为 <名称>-YYYY-MM-DD.log.gz。 log_file = "" [security] # 下游鉴权。空数组 = 不鉴权;建议部署时换成自己的 key。 api_keys = ["sk-dsfr-local-change-me"] [admin] enabled = true host = "127.0.0.1" port = 8001 # 留空时启动会生成一次性随机密码并打印到日志。 password = "admin123" [limits] # 同一站点的并发上游请求数;rate_per_minute = 0 表示不限流。 max_concurrent_per_site = 4 rate_per_minute = 0 [proxy] # 主线路,支持 http:// / https:// / socks5://,留空则直连。 url = "" # 主线路失败或 slow-start 超时后依次尝试的备用线路。 fallback_urls = [] # 主线路允许的首事件等待秒数(>0 且存在备用线路时生效)。 slow_start_seconds = 8 [proxypool] # 代理池:为每个站点绑定独立出口(Xray 分享链接 / 订阅 / ip:port 端点)。 # 选路为粘性:优先使用绑定列表中第一个健康节点,失败才切换;未绑定或 # 全部不健康时回退到上面的 [proxy] 主/备线路。Turnstile 求解与请求共用 # 同一出口(Cookie 与出口 IP 绑定,换出口后会自动重新求解)。 enabled = false check_interval_seconds = 120 # 健康检查间隔 check_timeout_seconds = 10 # 单次探测超时 check_url = "https://www.gstatic.com/generate_204" default_scheme = "http" # 裸 ip:port 的默认协议(http / socks5) # Xray 核心:留空 xray_path 且开启自动下载时,首次使用会下载到数据目录 # (data/xray.exe;核心配置写到 data/config.json)。分享链接(vless / vmess # / trojan / ss)由它承载;纯 ip:port / socks5:// 端点无需核心。 xray_path = "" xray_version = "" # 留空 = 最新版 xray_auto_download = true # 手动节点(名称限字母 / 数字 / - / _): # [proxypool.entries.node-a] # link = "vless://uuid@host:443?type=ws&security=tls&sni=example.com&path=/ws#node-a" # link = "socks5://user:pass@1.2.3.4:1080" # link = "1.2.3.4:8080" # 使用 default_scheme # link = "1.2.3.4:8080:user:pass" # enabled = true # 缺省即启用 # 订阅(按 interval_minutes 自动刷新;节点名形如 <订阅名>#xxxxxxxx): # [proxypool.subscriptions.home] # url = "https://example.com/api/v1/client/subscribe?token=…" # interval_minutes = 60 # enabled = true [upstream] timeout = 60.0 stream_timeout = 300.0 config_ttl_seconds = 60 auto_refresh = true refresh_retries = 4 retry_backoff_seconds = 1.0 user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/149.0.0.0 Safari/537.36" # 本站点配额耗尽时自动切换到其他站点的同款模型。 cross_site_failover = true # 站点对单次回复有约 1k token 的硬上限,大参数的工具调用 JSON 会被截断。 # 自动向上游追加「续写」轮次把 JSON 拼完整;若最终仍不闭合,会在截断处 # 强行补全闭合,返回内容写到哪算哪的部分工具调用,由客户端下一轮继续写。 # 0 = 关闭续写(每次截断都直接强行补全返回)。 continue_rounds = 20 [turnstile] # 默认关闭,且不内置任何求解服务。Token 获取方式三选一(provider): # api —— 调用你自己的求解服务 API(需 api_url / api_key,方式 1) # browser —— 用本机浏览器自动求解(需 browser_path,方式 2) # manual —— 只用控制台手动导入的 Cookie(方式 3) enabled = false provider = "api" # 方式 1:求解服务 API(api_style = "sync" 为默认 CapSolver 形状; # api_style = "ezsolver" 适配本地 EzSolver 服务,api_key 可留空) # api_url = "https://your-solver.example.com/turnstile/sync" # api_key = "REPLACE_ME" # 方式 2:本地浏览器自动获取(CDP 直连,无需 Playwright / Docker) # browser_path = "C:\\Program Files (x86)\\Microsoft\\Edge\\Application\\msedge.exe" # browser_headless = false # 默认有头窗口,过验证率更高 # browser_user_data_dir = "" # 可选:指向已有 profile(需先关掉正在运行的浏览器) # browser_timezone = "" # 可选:时区,与代理出口对齐,如 "Asia/Tokyo" # browser_locale = "" # 可选:如 "ja-JP",留空取站点语言 sitekey = "0x4AAAAAADlLZ3ljqZP6cQwq" action = "chat" # 求解超时:单次求解(浏览器 / 求解服务 API)的最长等待秒数,5–600。 timeout_seconds = 90 cookie_ttl_seconds = 10800 retries = 5 retry_backoff_seconds = 1.5 # ── Cookie 池(后台预热)───────────────────────────────── # 开启后,后台按 warm_check_seconds 巡检:Cookie 缺失 / 过期 / # 剩余 TTL 低于 warm_ratio 时主动重解并写回缓存,请求路径不再等待求解。 # provider = "manual" 时不预热(手动导入的 Cookie 无法自动续期)。 warm_enabled = false warm_ratio = 0.3 # 剩余 TTL 低于该比例(0.05–0.95)时触发预热 warm_check_seconds = 60 # 后台巡检间隔秒数(5–3600) # ── 配额哨兵(站点免费额度实时监控)────────────── # 用与聊天相同的出口 Cookie 定期查询站点余额接口(每日免费额度),结果 # 写入日志与后台 /api/overview 的 quota 区域;剩余低于 warn_ratio 时告警。 [quota] enabled = false check_seconds = 300 warn_ratio = 0.2 [runtime] data_dir = "./data" # ── Responses API 状态缓存(previous_response_id / GET /v1/responses/{id})── # 进程内、有界、带 TTL;store=false 的请求不写入。重启即失效。 [responses] store_capacity = 256 # 最多保存的响应条数(1–100000) store_ttl_seconds = 3600 # 条目存活秒数(1–604800) [sites.de] base_url = "https://deepseek.de" ajax_url = "https://deepseek.de/wp-admin/admin-ajax.php" sitekey = "0x4AAAAAADlLZ3ljqZP6cQwq" language = "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7" # 站点级出口绑定(代理池条目名或 "sub:订阅名",按顺序粘性选路); # 留空 = 使用 [proxy] 主/备线路。三个站点可各自独立配置。 # proxies = ["node-a", "sub:home"] # 只预热代理池线路(不预热 [proxy] 主/备;请求时仍可回落): # warm_pool_only = true [sites.es] base_url = "https://deepseek.es" ajax_url = "https://deepseek.es/wp-admin/admin-ajax.php" sitekey = "0x4AAAAAADlLZ3ljqZP6cQwq" language = "es-ES,es;q=0.9,en-US;q=0.8,en;q=0.7" [sites.fr] base_url = "https://deepseek.fr" ajax_url = "https://deepseek.fr/wp-admin/admin-ajax.php" sitekey = "0x4AAAAAADlLZ3ljqZP6cQwq" language = "fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7" [models.deepseek-v4-flash-de] site = "de" upstream_id = "deepseek-v4-flash" label = "DeepSeek V4-Flash DE" page_path = "/" bot_id = 27487 post_id = 106 [models.deepseek-v4-pro-de] site = "de" upstream_id = "deepseek-v4-pro" label = "DeepSeek V4-Pro DE" page_path = "/pro/" bot_id = 27533 post_id = 27177 [models.deepseek-v4-flash-es] site = "es" upstream_id = "deepseek-v4-flash" label = "DeepSeek V4-Flash ES" page_path = "/" bot_id = 27623 post_id = 27568 [models.deepseek-v4-pro-es] site = "es" upstream_id = "deepseek-v4-pro" label = "DeepSeek V4-Pro ES" page_path = "/pro/" bot_id = 27637 post_id = 27615 [models.deepseek-v4-flash-fr] site = "fr" upstream_id = "deepseek-v4-flash" label = "DeepSeek V4-Flash FR" page_path = "/" bot_id = 27645 post_id = 27569 [models.deepseek-v4-pro-fr] site = "fr" upstream_id = "deepseek-v4-pro" label = "DeepSeek V4-Pro FR" page_path = "/pro/" bot_id = 27647 post_id = 27616 # 模型别名:把客户端发来的任意模型名(Codex CLI / Claude Code 会发 gpt-* 、claude-* 等) # 映射到上面 [models.*] 里已启用的 id。键不区分大小写。 [model_aliases] "gpt-5" = "deepseek-v4-flash-de" "claude-sonnet-4-5" = "deepseek-v4-pro-de" # 默认模型:model 和 model_aliases 都没命中时降级到此模型(留空 = 未知模型仍 404)。 # 注意:别名解析是尽力而为的兼容手段,显式配置别名优于依赖降级。 # default_model = "deepseek-v4-flash-de"