README 的表格列常用变量,.env.example 是完整清单 —— 两者合计覆盖
75 个。本文补齐剩下 82 个只存在于源码里的开关:注释很全,但运营翻不到。
(2026-10-16 按 d3f0490 重测:全量 157。旧值 158 / 74 / 84 是 ab4e66f 树的口径:
9031b9b 把 CASCADE_MAX_WAIT_MS 写进 README(覆盖 +1),054806a 删掉一个开关的读取点
(全量 −1)。重测命令就是下面那段脚本。
2026-10-18 @706fc11 重测:160;新增 WINDSURFAPI_STREAM_COMMIT_MS、
WINDSURFAPI_TOOL_HYGIENE 与 DEVIN_BACKEND_TOKEN 三个读取点/文档项。)
数开关别用裸 grep 'env\.',有两个坑:一是 WINDSURFAPI_TRACE 这类名字是
WINDSURFAPI_TRACE_DIR 的前缀,正则不加边界会重复计数;二是相当一部分读取点
不长得像 env.FOO —— positiveIntEnv('FOO', 默认)(client.js/proto-trace.js/
conversation-pool.js)和 runtime-config.js 里 {env: 'FOO', def: …} 的表驱动写法
都是真读取点。只匹配 env.FOO 会漏掉 45 个(2026-10-16 用下面的脚本重测 @d3f0490:全量 157、裸 grep 112;ab4e66f 时点为 158 / 113 —— 差值仍是 45)。正确数法:
python3 - <<'PY'
import re,pathlib,subprocess
files=[f for f in subprocess.run(['git','ls-files','src'],capture_output=True,
text=True).stdout.split() if f.endswith('.js')]
PAT=re.compile(r"""(?:(?:process\.)?env\.([A-Z][A-Z0-9_]{2,})
|(?:process\.)?env\[\s*['"]([A-Z][A-Z0-9_]{2,})['"]
|positiveIntEnv\(\s*['"]([A-Z][A-Z0-9_]{2,})['"]
|\benv:\s*['"]([A-Z][A-Z0-9_]{2,})['"]
|\bconst\s+[A-Za-z_$][\w$]*\s*=\s*['"]([A-Z][A-Z0-9_]{2,})['"])""",re.X)
def strip(s): # 注释里的名字不算读取点
# 不能用 re.sub(r'/\*.*?\*/', '', s, flags=re.S) —— 本仓库有两个文件的
# **正则字面量里含 `*/`**(如 /\*\//),于是 `*/` 比 `/*` 多(identity-neutralize.js
# 是 9 比 7)。惰性匹配会在正则内部的 `*/` 处收尾,从那之后全部错配,把真代码删掉。
# 实测代价:WINDSURFAPI_NEUTRALIZE_CC_AGGRESSIVE 和 DEVIN_CONNECT_CRED_KEY
#(一个凭证开关)对统计和守卫双双隐形,而两者都是绿的。逐行处理即可避免。
out=[]; inB=False
for raw in s.split('\n'):
line=raw
if inB:
c=line.find('*/')
if c==-1: out.append(''); continue
line=line[c+2:]; inB=False
line=re.sub(r'/\*.*?\*/','',line) # 单行内自闭合的块注释
o=line.find('/*'); lc=line.find('//')
if o!=-1 and (lc==-1 or o<lc): inB=True; line=line[:o]
out.append(re.sub(r'//.*$','',line))
return '\n'.join(out)
names=set()
for f in files:
for m in PAT.finditer(strip(pathlib.Path(f).read_text(errors='replace'))):
n=next(g for g in m.groups() if g)
if n.startswith(('DEVIN_CONNECT_','WINDSURFAPI_','CASCADE_')): names.add(n)
print(len(names)) # 158(2026-08-10,合入 PR #249 之后)
PY第五种形式(const X = 'FOO' 然后 env[X])是 PR #249 带进来的,当时前四种
全部漏掉了它 —— 守卫绿着,统计却少算一个。所以这份清单的数字不要手抄,
跑上面的脚本。
每个默认值都是逐个打开源码站点读出来的,不是按名字推断。文档写错默认值比没文档更坏, 所以标了取值位置,可自行核对。
通用约定:这些开关只认精确的 '1' 或 '0',不认 true / yes / on。这是刻意的——
历史上 Number() / 真值重写把开关静默翻转过(#241、#242)。
src/dashboard/logger.js 默认按 UTC 日期追加 app/error JSONL 文件,内存环形缓冲最多
1000 条。Dashboard 的“清空”仅清当前页面,日志导出来自内存,不读取历史磁盘文件。
LOG_LEVEL 只控制控制台输出,文件与 Dashboard 保留所有级别。
以下限制由 src/dashboard/log-files.js 读取,默认全部关闭。修改环境变量或 .env
后重启服务;只接受非负安全整数,空值、负数、小数、无效值及换算后溢出的值视为 0。
三项可以独立启用,例如:
LOG_RETENTION_DAYS=14
LOG_MAX_FILE_MB=20
LOG_MAX_TOTAL_MB=500| 变量 | 默认 | 行为 |
|---|---|---|
LOG_RETENTION_DAYS |
0(关闭) |
保留 N 个 UTC 日历日期,包含当天和前 N-1 天;根据文件名日期判断,不依赖 mtime。启动、每小时及跨 UTC 日写入时删除过期日志。 |
LOG_MAX_FILE_MB |
0(关闭) |
每个新写入文件最多 N MiB(1 MiB = 1048576 字节)。按 UTF-8 字节计数,在完整 JSONL 行之间轮转为 app-YYYY-MM-DD-000001.jsonl 等。重启后继续最新分段。历史已有大文件不会被拆分。 |
LOG_MAX_TOTAL_MB |
0(关闭) |
app/error 文件合计最多 N MiB。启动、每小时及写入前清理,按日期、分段序号、文件名顺序淘汰最旧文件。容量优先于保留期限,必要时可淘汰当天日志。warn/error 在两类文件中各写一份,两份均计入容量。 |
只清理 DATA_DIR/logs/ 内匹配 app-YYYY-MM-DD[-NNNNNN].jsonl 或
error-YYYY-MM-DD[-NNNNNN].jsonl 的普通文件;未知文件、无效日期、符号链接和子目录保留,
不计入容量。单条记录若大于单文件或总容量上限,跳过磁盘写入,不拆成无效 JSONL;
内存、SSE 和控制台行为不变,控制台会提示写入/清理失败。IO 错误同样不阻断请求,后续写入会重试。
此策略要求每个日志目录只有一个进程写入;多副本需隔离各自的数据目录,不能把共享目录的
并发写入视为受全局容量约束。检查和删除失败时也不能保证硬容量上限,需处理目录权限和磁盘故障。
本功能不清理 .trace/、.wire-dump/、proto-trace、Language Server 自身日志或
Docker/PM2/stdout 日志;这些由各自的调试开关或部署层保留策略管理。
| 变量 | 默认 | 说明 |
|---|---|---|
CASCADE_REUSE_ALLOW_SHARED_API_KEY |
关 | 允许多个调用方共享同一个上游账号时复用 Cascade 会话(handlers/chat.js,=== '1')。上游会保留会话状态,所以开启后不同调用方有可能看到彼此的上下文。默认关是刻意的隔离边界,多租户场景不要开。 |
DEVIN_CONNECT_ALLOW_REMOTE_CRED_STORE |
关 | 允许非本机请求写凭证库(dashboard/api.js,=== '1')。还要求对端是 loopback —— 校验的是 peer 地址而不只是监听地址,因为反向代理后面监听地址永远是本机。 |
前两个默认开,关掉会让思维链泄漏到内容通道 —— 客户端看到重复文本或裸 <think> 标记。
第三个默认关,且当前不改变输出。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_CASCADE_THINK_REROUTE |
开 | Cascade 路径把带 think 标记的开头内容改道到 reasoning 通道(handlers/chat.js,|| '1') !== '0')。设 0 关闭。 |
DEVIN_ACP_CONFIG_OPTIONS |
关 | ACP session/new 后按 configOptions 调用 session/set_config_option 设置模型(devin-acp.js,=== '1')。默认关:live 的 option id/value 尚未校准。 |
WINDSURFAPI_TOOL_HYGIENE |
开 | 三方言请求/历史/egress 的工具名与 ID 卫生(handlers/{messages,responses,gemini}.js)。设 0 关闭,回到原始透传。 |
WINDSURFAPI_STREAM_COMMIT_MS |
5000 |
OpenAI chat 流的提交门等待窗口(server.js,0 = 关闭门,最大钳到 14000)。窗口内只缓冲 comment/role-only 帧;首个真实内容或错误帧立即决定提交。设 0 回到旧的「先写 200」行为。 |
WINDSURFAPI_REASONING_DEDUP |
开 | 抑制 reasoning 与 content 逐字重复的那一份。 |
WINDSURFAPI_NEUTRALIZE_CC_AGGRESSIVE |
关 | 强制走 Claude Code 的激进中和分支(handlers/identity-neutralize.js,|| '') === '1')。检测到 CC 客户端时该分支本来就会走,这个变量只是手动强制。目前该分支是保留状态 —— 源码注释写明「no CC-only rewrites are confirmed yet」,所以开它当前不改变输出。 |
这一组只在排查 native tool call 链路时才用得上。全部默认关或有内置默认值。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_FORCE_GPT_NATIVE_DIALECT |
关 | 对所有模型强制用 GPT 原生 tool call 方言,不再按模型族判断(handlers/tool-emulation.js,=== '1')。排查方言选择时用。 |
WINDSURFAPI_NATIVE_BRIDGE_NO_EMUL |
关 | 走 native bridge 时不再叠加 prompt 层的工具模拟(=== '1')。用来区分「原生解码坏了」和「模拟层坏了」。 |
WINDSURFAPI_NATIVE_TOOL_BRIDGE_POLL_AFTER_TOOL |
关 | 交出 tool result 后主动再轮询一次上游(client.js,=== '1')。只在 native 模式下有意义。 |
WINDSURFAPI_NATIVE_TOOL_BRIDGE_WEBFETCH_AUTO_APPROVE |
关 | 自动批准 read_url 抓取,不等确认(client.js 的 isReadUrlAutoApproveAllowed)。光开这个不够 —— 还必须用 ..._WEBFETCH_AUTO_APPROVE_ORIGINS 列出允许的 origin,名单为空时一律返回 false。双重门是刻意的:让模型自行发外部请求必须显式指定去哪。 |
WINDSURFAPI_NATIVE_TOOL_BRIDGE_CONFIG_RAW |
空 | 直接塞一段原始 bridge 配置(windsurf.js,` |
WINDSURFAPI_NATIVE_TOOL_BRIDGE_ALLOWLIST_NAMES |
空 | 覆盖工具白名单的名字,逗号分隔(cascade-native-bridge.js 的 csvListEnv)。留空用内置名单。 |
WINDSURFAPI_NATIVE_BRIDGE_STATS_KEY_LIMIT |
200 |
统计里最多保留多少个 key(native-bridge-stats.js,非有限值或 ≤0 时回落 200)。 |
WINDSURFAPI_NATIVE_BRIDGE_DECISION_RING_SIZE |
25 |
决策环形缓冲保留多少条(同上,回落 25)。调大能看更长的决策历史。 |
这五个默认开,所以只能往「关」的方向调。它们都是「设 0 才关闭」的写法 ——
写成别的值(false / off)不生效,除 RESPONSE_CACHE 外都只认精确的 '0'。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_ENV_LIFT |
开 | 把调用方的环境上下文提升进 prompt(handlers/chat.js,?? '1' 后 === '0' 关闭)。注意这个用 ?? '1' 而不是 || '1',且会 trim + 转小写。 |
WINDSURFAPI_LS_PER_PROXY_USER |
开 | 每个 proxy 用户独立一个 LS 实例(langserver.js,=== '0' 关闭)。关掉会让不同用户共享 LS,省内存但失去隔离。 |
WINDSURFAPI_NLU_RECOVERY |
开 | 意图抽取失败时走恢复路径(handlers/intent-extractor.js,=== '0' 时直接返回空数组)。 |
WINDSURFAPI_VARIANT_FALLBACK_ON_RATE_LIMIT |
开 | 撞限流时自动回落到同族其它变体(handlers/chat.js,=== '0' 关闭)。关掉后限流直接报错给客户端。 |
WINDSURFAPI_RESPONSE_CACHE |
开 | 响应缓存(cache.js)。链式兜底:RESPONSE_CACHE_ENABLED ?? WINDSURFAPI_RESPONSE_CACHE ?? '1',所以前者优先。这个认多种关闭写法(0/false/off/no)。 |
排查时才开。几个会往磁盘写内容,注意目录别落进打包或提交范围。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_TRACE |
关 | 是否写 trace(trace.js,|| '' 后 === '1')。注意它不门控 WINDSURFAPI_TRACE_DIR —— traceRoot() 无条件读目录变量,只是没开 trace 时不往里写。 |
WINDSURFAPI_TRACE_DIR |
<cwd>/.trace |
trace 落盘根目录(trace.js 的 traceRoot(),devin-connect.js 写上游 wire 字节时也读同一个变量)。每个请求一个子目录,按固定 leg 名分片:01-client-req / 02-routing / 03-upstream-req / 04-upstream-res / 05-client-res。上一行说过它不受 WINDSURFAPI_TRACE 门控;此前只作为那条说明的一部分出现,没有自己的条目。 |
WINDSURFAPI_PROTO_TRACE_DIR |
/data/proto-trace |
proto trace 落盘目录(|| '/data/proto-trace')。注意这是绝对路径默认值,和 WINDSURFAPI_TRACE_DIR(默认 <cwd>/.trace)不是一套。 |
WINDSURFAPI_PROTO_TRACE_STRINGS |
关 | 把 proto 字段的字符串内容写进 trace(proto-trace.js:814,=== '1')。关闭时只落 sha256,不落原文。开启后走 redactPreview() 脱敏:命名密钥(devin-session-token/api_key/idToken/refreshToken 等)、邮箱、任何 32+ 字符的高熵串都替换成 <redacted>,再截断到 240 字符。即便如此,开启后 trace 里会有真实 prompt 片段,排查完就关。 |
WINDSURFAPI_PROTO_TRACE_ERROR_STRINGS |
关 | 出错时额外输出字符串内容(=== '1')。和 PROTO_TRACE_STRINGS 一样走脱敏。 |
WINDSURFAPI_DUMP_SYSTEM_PROMPT |
关 | 把最终发给上游的 system prompt 打出来(windsurf.js,=== '1')。会输出完整 prompt 内容,排查完记得关。 |
WINDSURFAPI_PROBE_CANARY |
关 | 发探针金丝雀请求(=== '1')。校准脚本用。 |
WINDSURFAPI_STABLE_DEVICE |
空(= 每次随机) | 固定设备指纹种子(|| '')。设成固定值可让请求可复现 —— 对比抓包时有用,生产别设,指纹固定会更容易被识别。 |
WINDSURFAPI_SKIP_LS_CLEANUP |
关(= 会清理) | 名字是反的:!== '1' 时执行清理,所以设 1 才是「跳过」(index.js)。自更新后残留的 LS 会占着池端口累积,默认清理。同一台机器跑多个 WindsurfAPI 时才需要设 1。 |
WINDSURFAPI_RESTART_SUPERVISED |
关(= 自动探测) | 强制声明自己跑在守护进程下(restart.js,命中时返回 kind: 'override')。平时不需要设 —— systemd 自己会导出 INVOCATION_ID,代码据此自动识别。只在自动探测判错时用它兜底。 |
针对具体模型或具体客户端的窄开关。除末两个有数值默认外,其余默认关。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_FORCE_TOOL_DIALECT |
空(= 按模型族判断) | 强制指定工具方言。只接受这四个值:glm47 / openai_json_xml / kimi_k2 / gpt_native(handlers/tool-emulation.js 的白名单正则),写别的会被忽略而不是报错。比 FORCE_GPT_NATIVE_DIALECT 精确。 |
WINDSURFAPI_DISABLE_SONNET_TOOL_REUSE |
关 | 关掉 Sonnet 的工具复用(=== '1')。怀疑复用导致串工具时用。 |
WINDSURFAPI_OPUS47_THINKING_UIDS |
关 | Opus 4.7 用 thinking 专用的模型 uid(=== '1')。 |
WINDSURFAPI_FABRICATE_REJECT |
关 | 让上游拒绝时构造一个可读的拒绝响应而不是原样透传(handlers/chat.js,=== '1')。 |
DEVIN_CONNECT_COLLAPSE_SYSTEM |
关 | 把连续 system 内容包成 <system>...</system>,并入下一条 source=USER 消息。assistant/tool 历史不会提前消费它;末尾没有 user 时补一条 user。开启后原始 system 不再进入 request field #2,只有 tools 空-system guard 需要时才保留 benign placeholder。 |
WINDSURFAPI_NEUTRALIZE_CLINE_OBJECTIVE |
空(= 关) | 中和 Cline 客户端的 objective 段(|| '')。 |
WINDSURFAPI_SHOW_DISABLED_SPECIAL_AGENT_MODELS |
关 | 在模型列表里也显示上游标记为 disabled 的 special agent 模型(models.js,=== '1')。默认隐藏 —— 列出来客户端也调不通。 |
WINDSURFAPI_WEAK_MODEL_TOOL_LIMIT |
8 |
弱模型最多带几个工具定义(handlers/tool-emulation.js,非有限值或 ≤0 回落 8)。工具多了弱模型会选错。 |
DEVIN_CONNECT_RELOGIN_MAX_CONCURRENT |
2 |
同时最多几个账号并发重登(auth.js,>= 1 才生效否则回落 2,且会 Math.floor)。调大会更快恢复但更容易撞上游限流。 |
这几个开关控制往上游 protobuf 里写新字段。它们的 tag 号来自第三方 .proto
文件里的声明顺序,不是抓包测出来的 —— 而 prost 允许 tag 跳号,所以
声明顺序 ≠ wire tag。写错 tag 的表现不是报错,而是上游按别的字段解读那段字节。
所以:默认关是刻意的,不要因为"看起来该开"就打开。一次真实付费抓包能一起 解锁这一组;在那之前,开了就得自己承担猜错 tag 的后果。
| 变量 | 默认 | 说明 |
|---|---|---|
DEVIN_CONNECT_PROMPT_CACHE |
关 | 往请求里写 prompt 缓存字段(devin-connect.js,=== '1')。tag #13 猜自声明顺序。 |
DEVIN_CONNECT_TOOL_CHOICE |
关 | 发送 tool_choice(=== '1')。tag #12/#11 同样猜自声明顺序。 |
DEVIN_CONNECT_TOOL_CHOICE_TAGS |
空(= 用内置默认 tag) | 覆盖上面两个 tag,格式 choice=N,parallel=M(getToolChoiceTags)。只认 choice/parallel 两个键,其他键、非正整数、以及撞上已占用 tag 的值都会被跳过并打 warn,然后保留默认 —— 不是报错。撞 tag 的后果很隐蔽:choice=1 会和 814 字节的 ClientMetadata 同占 #1,protobuf 解码器取最后一个,等于用 tool_choice 覆盖上游认证元数据,表现为认证失败而不是"配置写错了"。这个防护是修过的真实缺陷,别绕过它。 |
DEVIN_CONNECT_SIGNATURE_TAG |
空(= 整个解码关闭) | thinking delta_signature 的 tag。这个是这组的总开关:没设或不是 (0, 2^29) 内的整数时 parseSignatureTagMap() 返回 null,下面两个一起失效。 |
DEVIN_CONNECT_SIGNATURE_TYPE_TAG |
空(= 该字段不解码) | signature type 的 tag,同样要求 (0, 2^29)。只在上一个已生效时才有意义。 |
DEVIN_CONNECT_SIGNATURE_THINKING_ID_TAG |
空(= 该字段不解码) | signature thinking_id 的 tag,约束同上。 |
DEVIN_CONNECT_USER_JWT |
关 | 用 GetUserJwt 短期凭证走 devin-connect 路径(=== '1')。写进 Metadata #21,tag 也来自声明顺序。 |
WINDSURFAPI_USER_JWT |
关 | 同一个功能在 Cascade 路径的开关(windsurf-api.js,=== '1')。两条路径各自独立,开一个不影响另一个。JWT 不落盘,剩余 TTL 低于 5 分钟(USER_JWT_MIN_TTL_MS)会重新领。 |
这些不是布尔开关,默认值都是实测或历史沿用下来的。它们的回落逻辑不一样 ——
有的校验 Number.isInteger 有的只校验 Number.isFinite,写非法值时的行为要看具体那行。
| 变量 | 默认 | 说明 |
|---|---|---|
DEVIN_CONNECT_WIRE_MAX_TOKENS |
8192 |
请求里 max_tokens 的默认值(devin-connect.js,要求正整数否则回落 8192)。和 handlers/messages.js、gemini.js 里的 || 8192 是一套。在模块加载时求值一次,改它要重启。 |
DEVIN_CONNECT_CATALOG_TTL_MS |
300000(5 分钟) |
每账号成功在线目录的复用时长(auth.js,有限数且 >=10000 才接受,否则回落 5 分钟)。TTL 内复用 last-known-good;过期后并行按账号刷新。空响应和失败不覆盖已有目录,也不推进成功时间。 |
DEVIN_CONNECT_MAX_INFLIGHT_PER_ACCOUNT |
0(关闭) |
单账号并发在途请求硬上限(auth.js,非负安全整数;0 = 不改变选择)。设为 N > 0 时,账号选择跳过已达 N 个在途请求的账号(含 sticky 绑定),让突发流量分散或 429,而不是继续堆在单账号。陈旧计数由 15 分钟下限的清扫回收。 |
WINDSURFAPI_TOOL_DESC_MAX |
500 |
工具描述的字符上限(toolDescMax(),要求 >= 0 的有限数否则回落 500)。0 = 不限长,不是"全砍掉"。注释说明当前只用于长度阈值判断。 |
CASCADE_1M_HISTORY_BYTES |
900000 |
1M 上下文模型的历史字节预算(client.js,positiveIntEnv)。非 1M 模型走 CASCADE_MAX_HISTORY_BYTES(默认 600000)。 |
CASCADE_MAX_HISTORY_BYTES |
600000 |
非 1M 模型的历史字节预算(client.js,positiveIntEnv)。源码注释记着这个默认值的来历:早先是 400KB,200KB 曾导致 30+ 轮工具调用的会话静默丢上下文,所以调到 600KB 留出余量。调小之前先想清楚这一点。此前只作为上一行的说明文字出现,没有自己的条目。 |
CASCADE_MAX_WAIT_MS |
600000 |
Cascade 单次等待上限(client.js)。曾只出现在 2.0.74 的 release notes 里;9031b9b 起 README 两语的 FAQ 也点名了它(README.md:642 / README.en.md:542,cold stall 的封顶值)—— 本文不再是它唯一的落点。 |
CASCADE_IDLE_GRACE_MS |
8000 |
空闲宽限(client.js)。 |
CASCADE_COLD_STALL_BASE_MS |
30000 |
冷启动停顿基数(client.js)。 |
| 变量 | 默认 | 说明 |
|---|---|---|
DEVIN_CONNECT_ACCOUNT_HOST |
关 | 允许账号的 apiServerUrl 覆盖请求 host(devin-connect.js + handlers/chat.js,=== '1')。生产环境必须保持关闭。 它当初是为"teams/自助 token 必须把 GetChatMessage 发去自己的 apiServerUrl"这个假设建的,而实测抓包已经否证了该假设 —— 真实 teams CLI 也发往 server.codeium.com。代码只留着供逆向时强制指定 host,不是修复手段;指错 host 会直接让对话不可用。 |
positiveIntEnv 的回落规则统一:非正整数一律用默认值,写 0 或负数不会"关掉"它。
| 变量 | 默认 | 说明 |
|---|---|---|
CASCADE_POLL_INTERVAL_MS |
500 |
轮询间隔。调小会显著增加上游请求数。 |
CASCADE_WARM_STALL_MS |
45000 |
已出过内容后的停顿判定。 |
CASCADE_WARM_STALL_THINKING_MS |
120000 |
同上,但处于 thinking 阶段时用这个(更宽松,推理本来就慢)。 |
CASCADE_WARM_STALL_TOOL_ACTIVE_MS |
180000 |
同上,工具执行中用这个(最宽松)。 |
CASCADE_TOOL_ACTIVE_GRACE_MS |
60000 |
工具活跃的宽限窗口。 |
CASCADE_STALL_RETRY_MIN_TEXT |
300 |
停顿重试要求的最小已出文本量(字符)。低于这个量才认为值得重试。 |
CASCADE_POOL_TTL_MS |
1800000(30 分钟) |
会话池条目存活时间(conversation-pool.js)。 |
只在 WINDSURFAPI_PROTO_TRACE 开启后才有意义。调大全都是放大输出体积,
排查完记得调回去。
| 变量 | 默认 | 说明 |
|---|---|---|
WINDSURFAPI_PROTO_TRACE_DEPTH |
8 |
递归解析深度上限(调用方显式传 opts.maxDepth 时以传入值为准)。 |
WINDSURFAPI_PROTO_TRACE_MAX_BYTES |
524288(512 KiB) |
单次 trace 的字节上限。 |
WINDSURFAPI_PROTO_TRACE_ERROR_DEPTH |
4 |
错误路径单独的深度上限。 |
WINDSURFAPI_PROTO_TRACE_ERROR_STRING_LIMIT |
8 |
错误里最多抽几个字符串。 |
WINDSURFAPI_PROTO_TRACE_SEMANTIC_FIELD_LIMIT |
12 |
语义化输出保留的字段数。 |
WINDSURFAPI_PROTO_TRACE_SEMANTIC_STEP_LIMIT |
40 |
语义化输出保留的步骤数。 |
WINDSURFAPI_PROTO_TRACE_READ_WRAPPER_CHILD_LIMIT |
24 |
read wrapper 展开的子字段数。 |
WINDSURFAPI_PROTO_TRACE_TOOL_CONFIG_UNKNOWN_LIMIT |
24 |
tool config 里未知字段的保留数。 |
这一组的特点是同时能从环境变量和运行时配置改(面板里也有),而且表里写着
min/max 边界,超界会被夹回而不是报错 —— 所以设了个离谱的值不会有任何提示。
表在 src/runtime-config.js,每行形如
{env: 'WINDSURFAPI_ERROR_STREAK_THRESHOLD', kind: 'int', def: 3, min: 1, max: 50}。
下面只列本文档其他小节没覆盖的部分(.env.example 已收录的不重复)。
| 变量 | 默认 | 边界 | 说明 |
|---|---|---|---|
WINDSURFAPI_BREAKER |
开(true) |
bool |
熔断总开关。关掉后下面所有 BREAKER_* 旋钮都不再起作用,坏账号也不会被摘掉。 |
WINDSURFAPI_ERROR_STREAK_THRESHOLD |
3 |
1–50 | 连续几次错误把账号摘出去(runtime-config.js 的 BREAKER_TUNABLES,表驱动)。和下一行的窗口配对:窗口内攒到这个次数才熔断。此前只作为下一行的说明文字出现,没有自己的条目 —— 表驱动开关容易这样漏掉,因为按 env.NAME 搜不到它。 |
WINDSURFAPI_ERROR_WINDOW_MS |
1800000(30 分钟) |
1e3–8.64e7 | 错误计数的统计窗口,和 ERROR_STREAK_THRESHOLD 配对使用。 |
WINDSURFAPI_SPEND_ON_DEMAND |
开(true) |
bool |
是否允许按需消费。涉及真实花钱,和下面的 ON_DEMAND_RESERVE_USD 是一套。 |
WINDSURFAPI_INTERNAL_ERROR_THRESHOLD |
2 |
1–50 | 连续几次内部错误触发隔离。 |
WINDSURFAPI_INTERNAL_QUARANTINE_MS |
120000 |
1e3–8.64e7 | 内部错误隔离时长。 |
WINDSURFAPI_ERROR_RECOVERY_MS |
900000 |
1e3–8.64e7 | 错误计数的恢复窗口。 |
WINDSURFAPI_BREAKER_BASE_MS |
null |
1e3–8.64e7 | 熔断退避基数。默认 null 表示不覆盖代码内的既有基数,不是 0。 |
WINDSURFAPI_BREAKER_FACTOR |
1.5 |
1.1–10 | 退避倍率(float)。 |
WINDSURFAPI_BREAKER_MAX_MS |
3600000 |
1e3–8.64e7 | 退避上限。 |
WINDSURFAPI_BREAKER_STREAK_START |
2 |
1–50 | 第几次连续失败开始退避。 |
WINDSURFAPI_NEW_ACCOUNT_GRACE_MS |
600000 |
0–8.64e7 | 新账号宽限期。 |
WINDSURFAPI_LAST_ACCOUNT_EXEMPT |
开(true) |
bool |
只剩最后一个账号时豁免熔断。这是默认开的,关掉意味着可能把全部账号熔断干净、服务完全不可用。 |
WINDSURFAPI_NEW_ACCOUNT_BASELINE |
开(true) |
bool |
新账号建立基线。 |
WINDSURFAPI_QUOTA_COOLDOWN |
开(true) |
bool |
配额冷却。 |
WINDSURFAPI_ON_DEMAND_RESERVE_USD |
0 |
0–100000 | 按需消费的预留额度(float,美元)。涉及真实花钱,改前想清楚。 |
至此三前缀开关 157 个全部有据可查:.env.example + README 覆盖 75 个(含 PR #249
的 WINDSURFAPI_LEAK_TRACE),本文覆盖其余 82 个(2026-10-16 按 d3f0490 重测)。这个不变式由
test/docs-consistency-guard.test.js 的
「every switch read in src/ is findable in some reader-facing doc」守着 ——
加新开关不写文档会直接让测试变红,不再依赖人记得。