-
Notifications
You must be signed in to change notification settings - Fork 219
Expand file tree
/
Copy path.env.example
More file actions
276 lines (239 loc) · 16.3 KB
/
Copy path.env.example
File metadata and controls
276 lines (239 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# 如果需要修改Docker暴露端口,请修改ports中的参数
# 示例(8080:3000) 则访问 http://localhost:8080
# To change the exposed Docker port, modify the ports parameter
# Example: (8080:3000) then access http://localhost:8080
SERVICE_PORT=3000
# Antidetect Tier 1: per-account fingerprint & header diversity
# Set to 'false' to instantly roll back to legacy static headers
# ANTIDETECT_TIER1_ENABLED=true
# Anthropic SSE `ping` 间隔(毫秒,最低 1000,默认 15000)
# 上游长时间不出内容时按此间隔发送协议内的 ping 事件,避免客户端把流判为卡死。
# 门禁拒绝后的补偿重试要整段重新生成,期间没有别的内容可发,是最长的静默来源。
# 若客户端或反向代理的空闲超时比这更短,调低它。
# Anthropic SSE `ping` interval in ms (floor 1000, default 15000). Sent during
# upstream silence so clients do not treat the stream as hung; the compensation
# retry regenerates from scratch and is the longest such window.
# ANTHROPIC_PING_INTERVAL_MS=15000
# Anthropic (/v1/messages) 与 OpenAI (/v1/chat/completions) 两条路径共用:一轮 Agent
# 回合里文本通道工具调用的上限(默认 24,钳在 4..256)。
# 模型在叙述的 [TOOL CALL] 之后失控(同一调用重复上百次、幻想整段 agent 会话)时,
# 第 N 个已放行的调用一到就终止上游,已放行的调用照常交付
# (stop_reason=tool_use / finish_reason=tool_calls)。更早的 delta 里已放行过调用之后,
# 再出现重复调用 / 被拒绝的调用 / 正文或思考同样立刻截断,不受此上限影响。
# Both agent paths (/v1/messages and /v1/chat/completions): cap on text-channel tool
# calls per agent turn (default 24, clamped to 4..256). When the model runs away after a
# narrated [TOOL CALL] (repeats the same call hundreds of times, hallucinates a whole
# agentic session), the upstream is cut right after the N-th admitted call and the
# admitted calls are still delivered (stop_reason=tool_use / finish_reason=tool_calls).
# Once a call was admitted in an earlier delta, a duplicate, a rejected call, or
# prose/thinking after it also cuts the turn, regardless of this cap.
# AGENT_TURN_MAX_TOOL_CALLS=24
# /v1/chat/completions 的 Agent 回合门禁。三个变量此前只存在于 src/config/index.js,
# 没有出现在本文件里 —— 而它们正是决定门禁何时把一次协议分歧变成 HTTP 错误的开关。
# AGENT_TURN_MAX_ATTEMPTS:同一回合最多重生几次(默认 3,clamp 到 2..6)。调高不会
# 提高成功率:重试复用同一个 chat_id 且 parentId 指向刚被拒的那条回复,三次抽样高度
# 相关,只会成倍放大对同一个账号的上游压力(实测这正是触发 WAF/RGV587 的原因)。
# AGENT_TURN_ALLOW_PROSE_WITH_TOOLS:允许正文与工具调用共存(默认 false)。Anthropic
# 路径无条件允许(anthropic.js#decideRetryReason),所以打开它就是两条路径对齐。
# AGENT_TURN_ACCEPT_BARE_FINAL:接受没有完成包装的裸正文(默认 false)。默认关闭是
# 刻意的:不能把"计划/进度汇报"当成任务完成交付给 agentic 客户端。
# Agent turn gate on /v1/chat/completions. These three lived only in src/config/index.js.
# AGENT_TURN_MAX_ATTEMPTS: regenerations per turn (default 3, clamped 2..6). Raising it
# does not raise the success rate — retries reuse the same chat_id with parentId pointing
# at the just-rejected response, so the draws are correlated; it mostly multiplies upstream
# load on one account (measured: that is what trips the WAF/RGV587 challenge).
# OpenAI Agent quota/WAF failures during stream consumption share this attempt budget.
# Before any content/reasoning is delivered, quota failures may switch to an untried
# healthy account; WAF allows only one switch. Full text is re-externalized on the new
# account (a WAF switch reuses the history prefix already uploaded), never compacted. Requests with user-uploaded media are not replayed across
# accounts. Exhausted pools stop; token refresh does not clear quota cooldowns. A WAF
# challenge cools no account: it follows Qwen's load, not the account.
# AGENT_TURN_ALLOW_PROSE_WITH_TOOLS: let prose coexist with tool calls (default false).
# The Anthropic path allows it unconditionally, so enabling it aligns both paths.
# AGENT_TURN_ACCEPT_BARE_FINAL: accept bare prose with no completion wrapper (default
# false). Off by default on purpose: a plan or a progress update must not be delivered to
# an agentic client as a finished task.
# AGENT_TURN_MAX_ATTEMPTS=3
# AGENT_TURN_ALLOW_PROSE_WITH_TOOLS=false
# AGENT_TURN_ACCEPT_BARE_FINAL=false
# 监听地址(非必填)
# Listen address (optional)
LISTEN_ADDRESS=
# Bun runs one process per container. Configure restarts and memory limits in Docker.
# Writable root for data/, logs/, caches/. Source defaults to the project root;
# standalone executables default to the current working directory.
# QWEN2API_RUNTIME_DIR=/var/lib/qwen2api
# API 密钥配置
# 支持单个或多个API_KEY,用逗号分隔
# 第一个API_KEY为管理员密钥,拥有全部权限(可访问前端管理页面、修改设置)
# 其他API_KEY为普通密钥,仅有调用API的权限,不能访问前端管理页面
#
# API key configuration
# Supports single or multiple API_KEYs, comma-separated
# The first API_KEY is the admin key with full access (dashboard, settings)
# Other API_KEYs are regular keys with API-only access (no dashboard)
#
# 单个密钥示例 / Single key example:
# API_KEY=sk-admin123
#
# 多个密钥示例 / Multiple keys example:
# API_KEY=sk-admin123,sk-user456,sk-user789
# 其中 / Where:
# - sk-admin123: 管理员密钥 / admin key (dashboard + settings + API)
# - sk-user456,sk-user789: 普通密钥 / regular keys (API only)
API_KEY=sk-123456
# 是否输出思考过程
# Whether to output the thinking process
OUTPUT_THINK=true
# 推理输出格式:默认 false = 推理走独立的 reasoning_content 字段;true = 旧版行为(<think> 并入 content)
# Reasoning output format: default false = reasoning goes to a separate reasoning_content field; true = legacy (<think> inside content)
LEGACY_REASONING_IN_CONTENT=false
# 搜索信息显示模式
# Search info display mode
SEARCH_INFO_MODE=table
# 简化模型映射
# true: 只返回基础模型,不包含thinking、search、image等变体
# false: 返回完整模型列表,包含所有变体
# Simplified model mapping
# true: only base models, without thinking/search/image variants
# false: full model list with all variants
SIMPLE_MODEL_MAP=false
# Agent 长上下文保护:当发往 Qwen Web 的 JSON 请求体超过此字节数时,
# 自动将完整工具定义和会话历史上传为文本文档,避免约 128 KiB 的 WAF/captcha 限制。
# Agent long-context protection: externalize the complete tool definitions and history
# as a text document before the Qwen Web request reaches its ~128 KiB WAF/captcha limit.
AGENT_CONTEXT_FILE_THRESHOLD_BYTES=92160
# 附件外置后仍保留在实时请求体中的工具协议与当前回合最大字节数。
# Maximum bytes of tool protocol/current-turn context kept in the live request after externalization.
AGENT_CONTEXT_LIVE_PROMPT_BYTES=49152
# 附件失败且请求不带工具时,压缩回退保留的最大字节数(带工具的请求改为返回可重试的 529/503)。
# Fallback budget when the attachment fails on a request WITHOUT tools (requests with tools get a retryable 529/503 instead).
AGENT_CONTEXT_FALLBACK_PROMPT_BYTES=86016
# 附件解析被 WAF 连续拦截 3 次后,在此秒数内不再上传(529 带 Retry-After);0 关闭。
# After 3 consecutive WAF challenges on the attachment parse, stop uploading for this many seconds (529 + Retry-After); 0 disables.
AGENT_PARSE_BREAKER_SECONDS=300
# 聊天生成被 WAF 连续拦截(被挤爆啦 / captcha)3 次后,在此秒数内不再发送聊天请求(529/503 带 Retry-After),之后只放行一个探测请求;0 关闭。
# After 3 consecutive WAF challenges on chat generation ("被挤爆啦" / captcha), send nothing for this many seconds (529/503 + Retry-After), then let a single probe through; 0 disables.
CHAT_CHALLENGE_BREAKER_SECONDS=60
# 附件解析速率上限:每个进程在 WINDOW 秒内最多 MAX 次 upload+parse,超出即返回短 Retry-After 的 529,避免触发按 IP 计数的 WAF。MAX=0 关闭。
# Attachment parse rate limit: at most MAX upload+parse per WINDOW seconds per process; beyond that a 529 with a short Retry-After, before the per-IP WAF starts challenging. MAX=0 disables.
AGENT_PARSE_MAX_PER_WINDOW=6
AGENT_PARSE_WINDOW_SECONDS=120
# 跨回合复用已解析的历史前缀:同一会话下一回合若历史以已上传文本开头,则复用同一附件,仅新增行内联(每 3-10 回合一次 parse)。false 关闭。
# Reuse the parsed history prefix across turns: when the next turn's history starts with the text already uploaded, the same attachment is reused and only the new lines go inline (one parse per 3-10 turns). false disables.
AGENT_CONTEXT_PREFIX_REUSE=true
# 条目自上传起的绝对存活秒数(过期 file_id 不报错,模型会静默丢失附件,故不宜过长);以及每进程最多缓存条目数。
# Absolute lifetime in seconds since upload (an expired file_id does not error — the model silently loses the attachment — so keep it short); and max cached entries per process.
AGENT_CONTEXT_PREFIX_TTL_SECONDS=1800
AGENT_CONTEXT_PREFIX_MAX_ENTRIES=200
# Redis链接(如果使用redis模式,则必填,当redis使用tls时将redis://替换为rediss://)
# Redis URL (required for redis mode; use rediss:// for TLS)
REDIS_URL=
# 批量添加账号时的登录并发数
# 建议范围 1-20,默认 5
# Batch login concurrency when adding accounts
# Recommended range: 1-20, default: 5
BATCH_LOGIN_CONCURRENCY=5
# 数据保存模式
# none 不保存数据,仅使用环境变量中的设置
# file 保存在本地文件中
# redis 保存到远程/本地redis中
# Data save mode
# none — no persistence, use env vars only
# file — save to local file
# redis — save to remote/local Redis
DATA_SAVE_MODE=none
# 账号与密码用 : 分隔,账号与账号间用 , 分隔(如果使用 redis / file 模式则不需要填写)
# 可选:在密码后用 | 附加该账号专属的代理 URL,覆盖全局 PROXY_URL
# Accounts — email:password pairs, comma-separated (not needed for redis/file mode)
# Optional: append |proxy_url after the password to set a per-account proxy
# overriding the global PROXY_URL fallback below
# 示例 / Examples:
# ACCOUNTS=user1@mail.com:pass1,user2@mail.com:pass2
# ACCOUNTS=user1@mail.com:pass1|http://10.0.0.1:8080,user2@mail.com:pass2|socks5://10.0.0.2:1080
ACCOUNTS=
# 日志配置
# 日志级别 (DEBUG, INFO, WARN, ERROR)
# Logging configuration
# Log level (DEBUG, INFO, WARN, ERROR)
LOG_LEVEL=INFO
# 是否启用文件日志
# Enable file logging
ENABLE_FILE_LOG=false
# 日志文件目录
# Log file directory
LOG_DIR=./logs
# 最大日志文件大小 (MB)
# Max log file size (MB)
MAX_LOG_FILE_SIZE=10
# 保留的日志文件数量
# Number of log files to retain
MAX_LOG_FILES=5
# ========== 代理与反代配置 / Proxy & Reverse Proxy ==========
# 自定义反代URL配置
# Custom reverse proxy URL
# QWEN_CHAT_PROXY_URL: 替代 https://chat.qwen.ai 的反代地址
# QWEN_CHAT_PROXY_URL: replaces https://chat.qwen.ai
# 示例 / Example: QWEN_CHAT_PROXY_URL=https://your-proxy.com
QWEN_CHAT_PROXY_URL=
# QWEN_CLI_PROXY_URL: 替代 https://portal.qwen.ai 的反代地址
# QWEN_CLI_PROXY_URL: replaces https://portal.qwen.ai
# 示例 / Example: QWEN_CLI_PROXY_URL=https://your-cli-proxy.com
QWEN_CLI_PROXY_URL=
# HTTP/HTTPS 代理配置
# 支持 HTTP, HTTPS, SOCKS5, SOCKS5H 代理(socks5h:// 由代理端解析 DNS)
# 全局回退代理:当账号未配置专属代理时使用(账号级代理可在 dashboard 或 ACCOUNTS 中设置)
# 优先级:account.proxy > PROXY_URL > 不使用代理
# HTTP/HTTPS proxy configuration
# Supports HTTP, HTTPS, SOCKS5, SOCKS5H proxies (socks5h:// resolves DNS at the proxy)
# Global fallback proxy — used only when an account has no dedicated proxy
# (per-account proxy can be set via the dashboard or ACCOUNTS env var)
# Priority: account.proxy > PROXY_URL > no proxy
# 示例 / Example: PROXY_URL=http://127.0.0.1:7890
# 示例 / Example: PROXY_URL=socks5://127.0.0.1:1080
PROXY_URL=
# ========== 入站模型名映射 / Incoming model name mapping ==========
# 把客户端发来的模型名映射成 Qwen 模型 id,只作用于 /v1/chat/completions 和 /v1/messages
# (图片、视频、CLI 端点不走这里)。Claude Code 的子代理会发 claude-opus-5 / claude-haiku-*
# (除非客户端自己设置了 ANTHROPIC_DEFAULT_OPUS/SONNET/HAIKU_MODEL 或 CLAUDE_CODE_SUBAGENT_MODEL;
# 服务端映射不需要任何客户端配置),OpenAI 风格客户端会发 gpt-*;不映射时上游返回 "Model not found"。
# 规则(两个端点相同):
# 1. 精确匹配优先,不区分大小写,末尾的 [..] 后缀先去掉(claude-opus-5[1m] 按 claude-opus-5 处理)
# 2. 上游已存在的 Qwen id(含 -thinking 等变体)原样透传,不受 * 影响
# 3. 其余名字用 * 条目;没有 * 时用上游第一个 t2t 模型并打印一条 warn。
# 仅在上游模型列表可用时生效:列表取不到时名字原样转发(打印一条 warn),不套用 *
# 目标 id 可带 -thinking 等后缀,后缀照常生效(会打开思考)。响应里的 model 字段回显解析后的
# Qwen id,不是别名。别名不需要出现在 /v1/models 里。落到回退目标的名字记录在进程内存中
# (每个进程一份,最多 100 个)。
# Maps incoming model names to Qwen model ids; applies to /v1/chat/completions and /v1/messages
# only (not images/videos/cli). Claude Code subagents send claude-opus-5 / claude-haiku-* (unless
# the client sets ANTHROPIC_DEFAULT_OPUS/SONNET/HAIKU_MODEL or CLAUDE_CODE_SUBAGENT_MODEL; the
# server-side map needs no client config), OpenAI-style clients send gpt-*; without a map the
# upstream answers "Model not found". Rule (same on both endpoints):
# 1. exact entry wins, case-insensitive; a trailing [..] suffix is stripped first (claude-opus-5[1m] = claude-opus-5)
# 2. names that already exist upstream (incl. -thinking variants) pass through, even with *
# 3. everything else uses the * entry; with no * the first upstream t2t model is used with a warn.
# Only while the upstream model list is available: if it cannot be fetched the name is
# forwarded unchanged (one warn) and * is not applied
# Targets may carry suffixes such as -thinking; they apply as usual (thinking switches on). The
# response `model` field echoes the resolved Qwen id, not the alias. Aliases work without being
# listed in /v1/models. Names that fell to the fallback are recorded in process memory (one list
# per process, 100 max).
# Dashboard:系统设置里的「模型映射」卡片可在线编辑。dashboard 保存过的映射优先于本变量(重启后仍生效);
# DATA_SAVE_MODE=none 时 dashboard 的修改只在内存里生效,重启即丢;「恢复 env 映射」会清掉保存的映射,
# 本变量重新生效。多个副本之间不自动同步,其他副本重启后才读到持久化映射。
# Dashboard: the "Model mapping" card in Settings edits this at runtime. A dashboard-saved map takes
# precedence over this variable (and survives restarts); with DATA_SAVE_MODE=none dashboard changes
# live in memory only and are lost on restart; "Restore env map" clears the saved map so this variable
# applies again. With several replicas a persisted map applies at once only in the process that
# handled the save; the others pick it up at their next restart.
# 格式 / Format: alias=qwen-model-id,alias2=qwen-model-id2,*=fallback-qwen-model-id
# 示例 / Example: MODEL_MAP=claude-opus-5=qwen3.8-max,*=qwen3.8-max-thinking
MODEL_MAP=
# ========== CLI 配置 / CLI Configuration ==========
# 是否启用 CLI 账户初始化(OAuth 设备授权流程需要人工确认,默认关闭避免初始化失败刷屏)
# true: 启用 CLI 初始化;false/不设置: 关闭(/cli/v1/chat/completions 返回 503)
# Enable CLI account initialization (OAuth device flow requires manual confirmation,
# disabled by default to avoid failure spam)
# true: enable; false/unset: disabled (cli endpoints return 503)
ENABLE_CLI=false