forked from dwgx/WindsurfAPI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path.env.example
More file actions
276 lines (262 loc) · 14.4 KB
/
Copy path.env.example
File metadata and controls
276 lines (262 loc) · 14.4 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
# ========== Server ==========
PORT=3003
# Bind host. Default binds beyond localhost (0.0.0.0) so Docker/LAN work; set to
# 127.0.0.1 to restrict to loopback. On a non-local bind the server FAILS CLOSED
# unless API_KEY (REST) and DASHBOARD_PASSWORD (dashboard writes) are set.
# HOST=0.0.0.0
# API key for incoming requests (leave empty for open access)
API_KEY=
# Directory for persisted JSON state and logs (Docker 推荐用 /data).
# Leave empty and it defaults to the repo/app root — set a writable path on
# bare-source installs so accounts.json / stats.json / logs don't scatter there.
DATA_DIR=
# ========== Reverse proxy / load balancer ==========
# Only honour X-Forwarded-For when a trusted proxy sits in front (e.g. the
# bundled docker-compose nginx LB, or openresty/Caddy). Without this every
# caller looks like the proxy's IP and the per-caller brute-force lockout
# collapses to one global bucket. TRUST_PROXY_HOPS = number of trusted proxies
# appended to XFF (default 1). The docker-compose file sets both automatically.
# TRUST_PROXY_X_FORWARDED_FOR=1
# TRUST_PROXY_HOPS=1
# In-memory duplicate response cache. Max bytes accepts b/k/kb/kib/m/mb/mib/g/gb/gib.
# RESPONSE_CACHE_ENABLED=1
# RESPONSE_CACHE_MAX_BYTES=16m
# ========== Codeium Auth ==========
# Option 1: Direct API key from Windsurf
CODEIUM_API_KEY=
# Option 2: Token from windsurf.com/show-auth-token
CODEIUM_AUTH_TOKEN=
# ========== Language Server ==========
# Path to the language server binary.
# Linux x64 default: /opt/windsurf/language_server_linux_x64
# Linux arm64 default: /opt/windsurf/language_server_linux_arm
# macOS Apple Silicon default: ~/.windsurf/language_server_macos_arm
# macOS Intel default: ~/.windsurf/language_server_macos_x64
LS_BINARY_PATH=/opt/windsurf/language_server_linux_x64
# Per-proxy language server data root.
# macOS local runs should use a user-writable directory, e.g. ~/.windsurf/data.
LS_DATA_DIR=/opt/windsurf/data
# gRPC port for language server
LS_PORT=42100
# Max live LS instances. Empty = memory-aware default (about 700MB per LS).
# Set low on small VPSes, especially when using per-proxy/per-user LS isolation.
# LS_MAX_INSTANCES=2
# Prewarm the no-proxy default LS on startup. Set 0 on low-memory hosts when
# all real traffic uses per-account proxies; LS will start lazily on demand.
# LS_PREWARM_DEFAULT=1
# How long a request waits for an active non-default LS to go idle before
# returning LS_POOL_EXHAUSTED / LS_MEMORY_GUARD.
# LS_POOL_WAIT_MS=30000
# Minimum available memory required before spawning another non-default LS. If
# unset, WindsurfAPI uses observed live LS RSS + margin after the first LS is
# ready, falling back to 700MB before any sample exists. Set this to pin a
# fixed operator budget. Accepts 700m / 1g / bytes.
# LS_SPAWN_MIN_AVAILABLE_BYTES=700m
# Dynamic RSS estimate floor/margin used only when LS_SPAWN_MIN_AVAILABLE_BYTES
# is unset.
# LS_OBSERVED_RSS_MIN_BYTES=384m
# LS_OBSERVED_RSS_MARGIN_PERCENT=35
# Disable memory guard only on hosts with external memory control/monitoring.
# LS_MEMORY_GUARD=1
# Stop idle non-default LS instances after this many milliseconds. 0 disables.
# LS_IDLE_TTL_MS=1200000
# Idle reaper interval. Empty = derived from LS_IDLE_TTL_MS.
# LS_IDLE_SWEEP_MS=300000
# Prewarm every configured proxy LS on startup. Default off to avoid memory spikes.
# LS_PREWARM_PROXIES=0
# Also prewarm/probe LS when adding accounts from Dashboard/batch/OAuth.
# Default off so bulk account import cannot spawn many heavy LSPs at once.
# LS_PREWARM_ON_ACCOUNT_ADD=0
# Background credit/token refresh skips accounts currently serving chat,
# account maintenance, or LS maintenance by default. Set 0 only if you want
# scheduled maintenance to run even when an account is busy.
# WINDSURFAPI_BACKGROUND_MAINTENANCE_SKIP_BUSY=1
# Native Cascade tool bridge. Default off because Cascade executes native
# Read/Bash-style tools in the remote Windsurf workspace, while most clients
# expect local execution.
# v2.0.139 production canary scope is intentionally narrow: without an
# explicit tool allowlist, only Bash / shell_command / run_command can route
# through the native bridge. Read/Grep/Glob/WebSearch/WebFetch are protocol
# matrix work, not production defaults. For local IDE tools (Claude Code,
# Cline, Codex, opencode), keep the default emulation path unless you are
# explicitly testing remote execution semantics.
# WINDSURFAPI_NATIVE_TOOL_BRIDGE=all_mapped
# Optional gray gates for real testing:
# WINDSURFAPI_NATIVE_TOOL_BRIDGE_TOOLS=Bash
# WINDSURFAPI_NATIVE_TOOL_BRIDGE_MODELS=claude-4.5-haiku
# WINDSURFAPI_NATIVE_TOOL_BRIDGE_API_KEYS=your-test-api-key
# Force bridge mode for mapped subsets only after the canary is proven:
# WINDSURFAPI_NATIVE_TOOL_BRIDGE=1
# Emergency hard-off:
# WINDSURFAPI_NATIVE_TOOL_BRIDGE_OFF=1
# Smoke an already-running native bridge deployment with:
# API_KEY=... BASE_URL=http://127.0.0.1:3003 npm run smoke:native-bridge
# Protocol trace is lab-only. For Read wrapper reverse engineering, prefer the
# dedicated child summary over global raw string dumps:
# WINDSURFAPI_PROTO_TRACE=1
# WINDSURFAPI_PROTO_TRACE_READ_WRAPPER_STRINGS=0
# Optional special-agent backend for models that do not work through direct
# Cascade chat (currently swe-1.6 / swe-1.6-fast / adaptive / arena-*).
# Default off. When enabled, the first PoC backend uses Devin CLI print mode:
# devin -p "<prompt>"
# Install/configure Devin CLI separately on the host/container and point this
# path at it. Do not bake it into the base image unless you want that runtime
# dependency for every deployment.
# WINDSURFAPI_SPECIAL_AGENT_BACKEND=devin-cli
# DEVIN_CLI_PATH=devin
# DEVIN_CLI_MODE=print
# DEVIN_MAX_PROCS=1
# DEVIN_QUEUE_TIMEOUT_MS=30000
# DEVIN_TIMEOUT_MS=600000
# Pass the checked-out Windsurf account apiKey to Devin CLI as WINDSURF_API_KEY.
# Set to 0 only when the CLI has its own login/session and you understand that
# the HTTP server still expects a normal WindsurfAPI account pool.
# DEVIN_CLI_USE_ACCOUNT_POOL=1
# Print mode refuses caller-local tools/media by default; ACP bridging should
# be used before enabling these in production.
# DEVIN_CLI_ALLOW_CLIENT_TOOLS=0
# DEVIN_CLI_ALLOW_MEDIA=0
# After configuring Devin CLI/ACP, validate the route with:
# API_KEY=... BASE_URL=http://127.0.0.1:3003 npm run smoke:special-agent
# ========== DEVIN_CONNECT (pure-HTTP Devin backend — POST-CASCADE SURVIVAL) ==========
# Cascade (the legacy LS-driven chat backend) is retiring. DEVIN_CONNECT is the
# pure-HTTP replacement: it talks directly to the Devin cloud GetChatMessage
# endpoint using the pooled session tokens (accounts.json) — NO language_server
# binary and NO local `devin` CLI required. This is the correct switch for a
# headless box (e.g. homecloud) that has neither binary installed.
#
# NOTE: DEVIN_ONLY is a DIFFERENT switch — it forces traffic onto the LOCAL
# Devin CLI subprocess and returns 503 if the `devin` binary is absent. For a
# binary-less host use DEVIN_CONNECT, not DEVIN_ONLY.
#
# Minimal cutover config: set DEVIN_CONNECT=1 and keep your existing API_KEY +
# account pool. Free-tier accounts resolve only `swe-1-6-slow`; paid selectors
# (claude-*/gpt-*/gemini-*) require a paid entitlement on the pooled account.
# DEVIN_CONNECT=1
#
# Single-token deploy (no account pool): provide the session token in env.
# DEVIN_CONNECT_TOKEN=
#
# Cross-account failover: max pooled-account hops after a dead session token.
# Default 2; set 0 to disable failover (same-account re-login still applies).
# DEVIN_CONNECT_FAILOVER_MAX=2
#
# --- Timeouts ---
# Idle (no-activity) socket timeout — resets on every byte. Default 120000.
# DEVIN_CONNECT_IDLE_TIMEOUT_MS=120000
# Absolute wall-clock cap from request start — the real backstop against a
# hung upstream that trickles bytes forever and defeats the idle timer.
# Default 600000 (10 min). Lower it for tighter SLAs.
# DEVIN_CONNECT_TIMEOUT_MS=600000
#
# --- Auto-recovery (recommended for unattended prod) ---
# Session tokens are opaque session_ids with no expiry/refresh — when one dies
# the ONLY recovery is a fresh email/password Auth1 login. Enable auto re-login
# + an encrypted credential store so a dead token self-heals. Accounts added via
# the email/password login path auto-store their password in this store.
# DEVIN_CONNECT_AUTO_RELOGIN=1
# DEVIN_CONNECT_CRED_KEY=<32+ char secret — required for auto-relogin to work>
# DEVIN_CONNECT_CRED_FILE=<path; default <DATA_DIR>/accounts.creds.json>
#
# --- Liveness probe (recommended) ---
# Zero-billable GetUserStatus sweep that detects + pre-emptively recovers dead
# tokens before a real request hits them. Off by default.
# DEVIN_CONNECT_LIVENESS_PROBE=1
# DEVIN_CONNECT_LIVENESS_INTERVAL_MS=600000
#
# --- Optional wire-tag decoders (frame-verified 2026-07-05; default off) ---
# actual_model_uid: report the concrete model that served a request (differs
# from the requested selector for router models). Frame-verified at metadata #7.9.
# DEVIN_CONNECT_ACTUAL_MODEL_TAG=9
# Native tool_call decode (repeated ChatToolCall). Off = prompt emulation owns
# tool calls. Only set once calibrated against a paid tool-using capture.
# DEVIN_CONNECT_TOOL_CALL_TAGS=outer=6,id=1,name=2,arguments_json=3
# Send the role-priming chunk eagerly (pre-2.0.146 behavior). Default defers it
# until the first real delta so first-connect transient errors keep recovery armed.
# DEVIN_CONNECT_EAGER_PRIME=1
#
# --- Misc bounds ---
# Cap the number of distinct model names the dashboard stats map tracks
# (overflow folds into an "(other)" bucket). Default 500; 0 = unbounded.
# STATS_MAX_MODELS=500
#
# Validate the whole path post-deploy with:
# API_KEY=... BASE_URL=http://127.0.0.1:3003 npm run smoke:devin-connect
# (set CONNECT_SMOKE_REAL_CALLS=0 to run preflight only, zero billable calls)
# ========== Dashboard ==========
# Dashboard password — protects /dashboard and all /dashboard/api/* endpoints.
# The dashboard now FAILS CLOSED by default: with no DASHBOARD_PASSWORD and no
# API_KEY set, unauthenticated requests are denied even on a localhost bind.
# Set DASHBOARD_PASSWORD (or API_KEY, which is accepted as the dashboard secret
# on localhost) for any real deployment.
DASHBOARD_PASSWORD=
# Opt back into the old open-on-localhost convenience (single-user dev only).
# When =1, a localhost bind with no secret configured is treated as authed.
# Discouraged; leave unset for fail-closed. Never enable on an internet bind.
DASHBOARD_ALLOW_NO_AUTH=
# CSV allowlist of origins reflected in Access-Control-Allow-Origin for the
# dashboard API. Unset = no cross-origin (same-origin only). Do NOT use "*".
DASHBOARD_CORS_ORIGINS=
# When =1, /dashboard/api/self-update may hard-reset (git reset --hard) even if
# it would drop unpushed local commits. Default: refuse and report. Opt-in only.
DASHBOARD_ALLOW_HARD_RESET=
# ========== Astraflow (OpenAI-compatible, 200+ models — https://astraflow.ucloud-global.com) ==========
# Global endpoint (env: ASTRAFLOW_API_KEY) — base URL: https://api-us-ca.umodelverse.ai/v1
ASTRAFLOW_API_KEY=
# China endpoint (env: ASTRAFLOW_CN_API_KEY) — base URL: https://api.modelverse.cn/v1
ASTRAFLOW_CN_API_KEY=
# ========== Advanced ==========
CODEIUM_API_URL=https://server.self-serve.windsurf.com
DEFAULT_MODEL=claude-4.5-sonnet-thinking
MAX_TOKENS=8192
LOG_LEVEL=info
# ========== 429 缓解 / 限流调优 (2026-07-12: 默认已开启) ==========
# 这三个旋钮治理 Claude Code / OpenCode 的 "429 死循环":单号被限流 → 网关秒拒
# 429 → 客户端立即重试 → 冷却越叠越长 → 打穿账号池。都是运行时 tunable(面板
# 设置页可热调,不重启),也可用下面的环境变量固定。2026-07-12 起默认值已从
# "字节等价关闭" 翻为 "开启";把值改回括号里的旧默认即可回退。
#
# F1 降级放行:整个可用池仅被"瞬态限流"(非配额耗尽)时,不甩 429,而是选一个
# "最不糟、只是短暂冷却"的号继续服务。配额干井(quotaResetAt)仍严格排除。
# 默认 true(旧默认 false=硬 429)。设 0 关闭。
# WINDSURFAPI_DEGRADED_SERVE=1
#
# F2 裸 429 短冷却:上游给裸 429(无 Retry-After reset)时账号冷却时长(毫秒)。
# 默认 15000(15s);旧默认 300000(5min)。KiroStudio 生产数据显示裸 burst 几秒
# 自愈,冻 5min 是小池雪崩源。breaker 指数退避仍会拉长重复触发的号。
# WINDSURFAPI_RL_BURST_MS=15000
#
# F3 客户端退避地板:给客户端的 Retry-After 响应头设最小值(毫秒),掐断"1s 提示
# → 立即重试"的热循环。默认 30000(30s);旧默认 0(无地板)。注意:影响所有 429
# 响应(不止 CC),所有客户端至少等这么久。ceil 默认 600000(10min)只削超长值。
# WINDSURFAPI_RL_CLIENT_BACKOFF_FLOOR_MS=30000
# WINDSURFAPI_RL_CLIENT_BACKOFF_CEIL_MS=600000
# ========== Cascade Reuse (single-user Claude Code optimization) ==========
# Caller-based fallback: when fingerprint misses, reuse the latest cascade
# for the same caller+model. Set to 1 for single-user Claude Code setups.
CASCADE_REUSE_BY_CALLER=0
# Max pool entries. Single-user setups can set to 1-5.
CASCADE_POOL_MAX=500
# Don't hash system prompt (reduces fingerprint drift from Claude Code's
# dynamic system prompt). Already defaults to 0.
# CASCADE_REUSE_HASH_SYSTEM=0
# ========== Security ==========
# Allow private/internal hosts (e.g., 192.168.x.x, 10.x.x.x, localhost) in proxy tests.
# Set to 1 for local deployments where you need to test proxies on private networks.
# Leave empty or set to 0 for public-facing deployments (default: only public hosts allowed).
ALLOW_PRIVATE_PROXY_HOSTS=
# Run the REST API with NO API_KEY (fail-open). Default OFF = fail closed: a
# request without a matching API_KEY is rejected even on a local bind, because
# "local bind" is not "no proxy" (a same-host reverse proxy makes every request
# look loopback). Set to 1 ONLY for genuine local/dev use on a local bind; never
# on a public bind. The Windows exe auto-generates an API_KEY so it never needs this.
# WINDSURFAPI_ALLOW_UNAUTHENTICATED=
# Let the chat API_KEY double as the dashboard password on a verified-local
# client (single-secret convenience). Default OFF = the dashboard requires a real
# DASHBOARD_PASSWORD. A shared chat key granting full operator access is a footgun,
# and a reverse-proxy misconfig can make a remote client look local — so this is
# opt-in. If you enable it, also set TRUST_PROXY_X_FORWARDED_FOR=1 behind a proxy.
# DASHBOARD_ALLOW_API_KEY_AS_PASSWORD=
# Open the dashboard with NO secret at all, from a verified-local client only.
# Default OFF = fail closed. Legacy single-user open-local convenience.
# DASHBOARD_ALLOW_NO_AUTH=