@viudes/windsurf-api 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.env.example ADDED
@@ -0,0 +1,148 @@
1
+ # ========== Server ==========
2
+ PORT=3003
3
+ # API key for incoming requests (leave empty for open access)
4
+ API_KEY=
5
+ # Directory for persisted JSON state and logs.
6
+ # Default: ~/.windsurf-api (a hidden per-user folder; cross-platform). Docker deployments should use /data.
7
+ DATA_DIR=
8
+
9
+ # In-memory duplicate response cache. Max bytes accepts b/k/kb/kib/m/mb/mib/g/gb/gib.
10
+ # RESPONSE_CACHE_ENABLED=1
11
+ # RESPONSE_CACHE_MAX_BYTES=16m
12
+
13
+ # ========== Codeium Auth ==========
14
+ # Option 1: Direct API key from Windsurf
15
+ CODEIUM_API_KEY=
16
+
17
+ # Option 2: Token from windsurf.com/show-auth-token
18
+ CODEIUM_AUTH_TOKEN=
19
+
20
+ # ========== Language Server ==========
21
+ # Path to the language server binary.
22
+ # Linux x64 default: /opt/windsurf/language_server_linux_x64
23
+ # Linux arm64 default: /opt/windsurf/language_server_linux_arm
24
+ # macOS Apple Silicon default: ~/.windsurf/language_server_macos_arm
25
+ # macOS Intel default: ~/.windsurf/language_server_macos_x64
26
+ LS_BINARY_PATH=/opt/windsurf/language_server_linux_x64
27
+ # Per-proxy language server data root.
28
+ # macOS local runs should use a user-writable directory, e.g. ~/.windsurf/data.
29
+ LS_DATA_DIR=/opt/windsurf/data
30
+ # gRPC port for language server
31
+ LS_PORT=42100
32
+ # Max live LS instances. Empty = memory-aware default (about 700MB per LS).
33
+ # Set low on small VPSes, especially when using per-proxy/per-user LS isolation.
34
+ # LS_MAX_INSTANCES=2
35
+ # Prewarm the no-proxy default LS on startup. Set 0 on low-memory hosts when
36
+ # all real traffic uses per-account proxies; LS will start lazily on demand.
37
+ # LS_PREWARM_DEFAULT=1
38
+ # How long a request waits for an active non-default LS to go idle before
39
+ # returning LS_POOL_EXHAUSTED / LS_MEMORY_GUARD.
40
+ # LS_POOL_WAIT_MS=30000
41
+ # Minimum available memory required before spawning another non-default LS. If
42
+ # unset, WindsurfAPI uses observed live LS RSS + margin after the first LS is
43
+ # ready, falling back to 700MB before any sample exists. Set this to pin a
44
+ # fixed operator budget. Accepts 700m / 1g / bytes.
45
+ # LS_SPAWN_MIN_AVAILABLE_BYTES=700m
46
+ # Dynamic RSS estimate floor/margin used only when LS_SPAWN_MIN_AVAILABLE_BYTES
47
+ # is unset.
48
+ # LS_OBSERVED_RSS_MIN_BYTES=384m
49
+ # LS_OBSERVED_RSS_MARGIN_PERCENT=35
50
+ # Disable memory guard only on hosts with external memory control/monitoring.
51
+ # LS_MEMORY_GUARD=1
52
+ # Stop idle non-default LS instances after this many milliseconds. 0 disables.
53
+ # LS_IDLE_TTL_MS=1200000
54
+ # Idle reaper interval. Empty = derived from LS_IDLE_TTL_MS.
55
+ # LS_IDLE_SWEEP_MS=300000
56
+ # Prewarm every configured proxy LS on startup. Default off to avoid memory spikes.
57
+ # LS_PREWARM_PROXIES=0
58
+ # Also prewarm/probe LS when adding accounts from Dashboard/batch/OAuth.
59
+ # Default off so bulk account import cannot spawn many heavy LSPs at once.
60
+ # LS_PREWARM_ON_ACCOUNT_ADD=0
61
+ # Background credit/token refresh skips accounts currently serving chat,
62
+ # account maintenance, or LS maintenance by default. Set 0 only if you want
63
+ # scheduled maintenance to run even when an account is busy.
64
+ # WINDSURFAPI_BACKGROUND_MAINTENANCE_SKIP_BUSY=1
65
+
66
+ # Native Cascade tool bridge. Default off because Cascade executes native
67
+ # Read/Bash-style tools in the remote Windsurf workspace, while most clients
68
+ # expect local execution.
69
+ # v2.0.139 production canary scope is intentionally narrow: without an
70
+ # explicit tool allowlist, only Bash / shell_command / run_command can route
71
+ # through the native bridge. Read/Grep/Glob/WebSearch/WebFetch are protocol
72
+ # matrix work, not production defaults. For local IDE tools (Claude Code,
73
+ # Cline, Codex, opencode), keep the default emulation path unless you are
74
+ # explicitly testing remote execution semantics.
75
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE=all_mapped
76
+ # Optional gray gates for real testing:
77
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE_TOOLS=Bash
78
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE_MODELS=claude-4.5-haiku
79
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE_API_KEYS=your-test-api-key
80
+ # Force bridge mode for mapped subsets only after the canary is proven:
81
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE=1
82
+ # Emergency hard-off:
83
+ # WINDSURFAPI_NATIVE_TOOL_BRIDGE_OFF=1
84
+ # Smoke an already-running native bridge deployment with:
85
+ # API_KEY=... BASE_URL=http://127.0.0.1:3003 npm run smoke:native-bridge
86
+ # Protocol trace is lab-only. For Read wrapper reverse engineering, prefer the
87
+ # dedicated child summary over global raw string dumps:
88
+ # WINDSURFAPI_PROTO_TRACE=1
89
+ # WINDSURFAPI_PROTO_TRACE_READ_WRAPPER_STRINGS=0
90
+
91
+ # Optional special-agent backend for models that do not work through direct
92
+ # Cascade chat (currently swe-1.6 / swe-1.6-fast / adaptive / arena-*).
93
+ # Default off. When enabled, the first PoC backend uses Devin CLI print mode:
94
+ # devin -p "<prompt>"
95
+ # Install/configure Devin CLI separately on the host/container and point this
96
+ # path at it. Do not bake it into the base image unless you want that runtime
97
+ # dependency for every deployment.
98
+ # WINDSURFAPI_SPECIAL_AGENT_BACKEND=devin-cli
99
+ # DEVIN_CLI_PATH=devin
100
+ # DEVIN_CLI_MODE=print
101
+ # DEVIN_MAX_PROCS=1
102
+ # DEVIN_QUEUE_TIMEOUT_MS=30000
103
+ # DEVIN_TIMEOUT_MS=600000
104
+ # Pass the checked-out Windsurf account apiKey to Devin CLI as WINDSURF_API_KEY.
105
+ # Set to 0 only when the CLI has its own login/session and you understand that
106
+ # the HTTP server still expects a normal WindsurfAPI account pool.
107
+ # DEVIN_CLI_USE_ACCOUNT_POOL=1
108
+ # Print mode refuses caller-local tools/media by default; ACP bridging should
109
+ # be used before enabling these in production.
110
+ # DEVIN_CLI_ALLOW_CLIENT_TOOLS=0
111
+ # DEVIN_CLI_ALLOW_MEDIA=0
112
+ # After configuring Devin CLI/ACP, validate the route with:
113
+ # API_KEY=... BASE_URL=http://127.0.0.1:3003 npm run smoke:special-agent
114
+
115
+ # ========== Dashboard ==========
116
+ # Dashboard password — protects /dashboard and all /dashboard/api/* endpoints.
117
+ # If empty AND API_KEY is also empty, dashboard is completely open (anyone can
118
+ # view accounts, API keys, logs, and trigger updates). Set this for any
119
+ # internet-facing deployment.
120
+ DASHBOARD_PASSWORD=
121
+
122
+ # ========== Astraflow (OpenAI-compatible, 200+ models — https://astraflow.ucloud-global.com) ==========
123
+ # Global endpoint (env: ASTRAFLOW_API_KEY) — base URL: https://api-us-ca.umodelverse.ai/v1
124
+ ASTRAFLOW_API_KEY=
125
+ # China endpoint (env: ASTRAFLOW_CN_API_KEY) — base URL: https://api.modelverse.cn/v1
126
+ ASTRAFLOW_CN_API_KEY=
127
+
128
+ # ========== Advanced ==========
129
+ CODEIUM_API_URL=https://server.self-serve.windsurf.com
130
+ DEFAULT_MODEL=claude-4.5-sonnet-thinking
131
+ MAX_TOKENS=8192
132
+ LOG_LEVEL=info
133
+
134
+ # ========== Cascade Reuse (single-user Claude Code optimization) ==========
135
+ # Caller-based fallback: when fingerprint misses, reuse the latest cascade
136
+ # for the same caller+model. Set to 1 for single-user Claude Code setups.
137
+ CASCADE_REUSE_BY_CALLER=0
138
+ # Max pool entries. Single-user setups can set to 1-5.
139
+ CASCADE_POOL_MAX=500
140
+ # Don't hash system prompt (reduces fingerprint drift from Claude Code's
141
+ # dynamic system prompt). Already defaults to 0.
142
+ # CASCADE_REUSE_HASH_SYSTEM=0
143
+
144
+ # ========== Security ==========
145
+ # Allow private/internal hosts (e.g., 192.168.x.x, 10.x.x.x, localhost) in proxy tests.
146
+ # Set to 1 for local deployments where you need to test proxies on private networks.
147
+ # Leave empty or set to 0 for public-facing deployments (default: only public hosts allowed).
148
+ ALLOW_PRIVATE_PROXY_HOSTS=
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 andersonviudes
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,135 @@
1
+ # windsurf-openai
2
+
3
+ Turn [Windsurf](https://windsurf.com) (formerly Codeium) cloud models into standard, drop-in APIs:
4
+
5
+ - `POST /v1/chat/completions` — OpenAI-compatible (any OpenAI SDK)
6
+ - `POST /v1/messages` — Anthropic-compatible (Claude Code / Cline / Cursor)
7
+ - `POST /v1/responses` — OpenAI Responses API
8
+ - `GET /v1/models` — list available models
9
+
10
+ 100+ models (Claude, GPT-5.x, Gemini, Grok, Qwen, Kimi, GLM, SWE, …). Pure Node.js, **zero npm dependencies**, requires Node `>=24`.
11
+
12
+ > Fork of [dwgx/WindsurfAPI](https://github.com/dwgx/WindsurfAPI), rewritten in English with a `windsurf-api` CLI. MIT licensed — see [LICENSE](LICENSE).
13
+
14
+ ## Quick start (CLI)
15
+
16
+ ```bash
17
+ npm install -g . # from a clone (or `npm link` for dev)
18
+
19
+ windsurf-api install # write .env, create dirs, download the Language Server
20
+ windsurf-api login --token <windsurf-token> # add an account (get the token below)
21
+ windsurf-api start --port 3003 # boot the proxy
22
+ ```
23
+
24
+ Other commands: `windsurf-api accounts` (list the pool), `status` (pool summary), `--help` (all flags). Flags like `--port`, `--api-key`, `--ls-binary` override `.env`.
25
+
26
+ > The Language Server is Linux/macOS only. On Windows, `install` scaffolds `.env` and the directories but skips the download — use Docker or WSL2, or point `--ls-binary` at a Windsurf desktop `language_server` binary. Prebuilt single-file executables are also attached to each [GitHub Release](https://github.com/andersonviudes/windsurf-openai/releases).
27
+
28
+ ## Docker
29
+
30
+ ```bash
31
+ cp .env.example .env
32
+ docker compose up -d --build
33
+ docker compose logs -f
34
+ ```
35
+
36
+ State persists under `./.docker-data/`; the container auto-downloads the Language Server on first boot if it isn't already there.
37
+
38
+ ## Add an account
39
+
40
+ Grab your token from [windsurf.com/show-auth-token](https://windsurf.com/show-auth-token), then either:
41
+
42
+ ```bash
43
+ windsurf-api login --token YOUR_TOKEN
44
+ # or over HTTP:
45
+ curl -X POST http://localhost:3003/auth/login \
46
+ -H "Content-Type: application/json" \
47
+ -d '{"token": "YOUR_TOKEN"}'
48
+ ```
49
+
50
+ Or open the dashboard at `http://YOUR_IP:3003/dashboard` and sign in with Google / GitHub / email — it adds the account to the pool automatically.
51
+
52
+ ## Use it
53
+
54
+ OpenAI SDK:
55
+
56
+ ```python
57
+ from openai import OpenAI
58
+ client = OpenAI(base_url="http://YOUR_IP:3003/v1", api_key="YOUR_API_KEY")
59
+ r = client.chat.completions.create(
60
+ model="claude-sonnet-4.6",
61
+ messages=[{"role": "user", "content": "Hello"}],
62
+ )
63
+ print(r.choices[0].message.content)
64
+ ```
65
+
66
+ Claude Code:
67
+
68
+ ```bash
69
+ export ANTHROPIC_BASE_URL=http://YOUR_IP:3003
70
+ export ANTHROPIC_API_KEY=YOUR_API_KEY
71
+ claude
72
+ ```
73
+
74
+ The OpenAI surface supports streaming, tool/function calling, JSON mode, image inputs, and real token usage. List models with `GET /v1/models`.
75
+
76
+ > **Cursor** blocks model names containing `claude` client-side — use aliases like `sonnet-4.6` or `opus-4.6` instead. GPT / Gemini names work as-is.
77
+
78
+ ## Configuration
79
+
80
+ Configure via environment variables (or `.env`). The common ones:
81
+
82
+ | Variable | Default | Description |
83
+ |---|---|---|
84
+ | `PORT` | `3003` | Service port |
85
+ | `API_KEY` | empty | Required on requests when set; empty disables auth |
86
+ | `HOST` | `0.0.0.0` | Bind host (`127.0.0.1` for localhost-only) |
87
+ | `DATA_DIR` | `~/.windsurf-api` | Persisted state and logs (`/data` in Docker) |
88
+ | `DEFAULT_MODEL` | `claude-4.5-sonnet-thinking` | Model used when none is given |
89
+ | `MAX_TOKENS` | `8192` | Default max response tokens |
90
+ | `LS_BINARY_PATH` | `/opt/windsurf/language_server_linux_x64` | Path to the Language Server binary |
91
+ | `DASHBOARD_PASSWORD` | empty | Dashboard password (empty = none) |
92
+
93
+ See [`.env.example`](.env.example) for the full, annotated list (proxy, account pool, LS pool tuning, lab/experimental flags).
94
+
95
+ ### Config file (fallback below ENV)
96
+
97
+ Instead of (or alongside) environment variables, you can drop a `config.json` next to the app — a
98
+ flat JSON file keyed by the same names as the env vars. It is a **fallback**: anything already set
99
+ in the environment wins, and the file only fills what's missing. Precedence is:
100
+
101
+ ```
102
+ CLI flags > real ENV > .env > config.json > built-in defaults
103
+ ```
104
+
105
+ ```json
106
+ {
107
+ "PORT": "3003",
108
+ "API_KEY": "sk-...",
109
+ "LS_BINARY_PATH": "/opt/windsurf/language_server_linux_x64",
110
+ "CODEIUM_AUTH_TOKEN": "..."
111
+ }
112
+ ```
113
+
114
+ Copy [`config.example.json`](config.example.json) to `config.json` (it's gitignored — it holds
115
+ secrets). `windsurf-api install` writes both `.env` and `config.json` for you. Keys prefixed with
116
+ `_` are treated as comments and ignored.
117
+
118
+ **Required to boot:** the server refuses to start unless at least one auth source is configured —
119
+ `CODEIUM_API_KEY`, `CODEIUM_AUTH_TOKEN`, `CODEIUM_EMAIL` + `CODEIUM_PASSWORD`, or a non-empty
120
+ `accounts.json`. Set `WINDSURFAPI_ALLOW_NO_AUTH=1` to start empty and add accounts later from the
121
+ dashboard.
122
+
123
+ ## Dashboard
124
+
125
+ `http://YOUR_IP:3003/dashboard` — account management, subscription/balance detection, model whitelist/blacklist, per-account proxies, live logs, and latency/usage stats.
126
+
127
+ ## How it works
128
+
129
+ The proxy translates each request into Windsurf's gRPC/Cascade protocol and relays it through a locally-spawned Language Server, managing a self-healing account pool (round-robin, rate limits, failover) along the way.
130
+
131
+ This is a **chat API, not an IDE agent** — it only passes `tool_use` / `tool_result` through. Your client (Claude Code, Cline, Cursor, Aider) is what actually reads and writes local files. If the model says it "can't access the filesystem", that's expected: drive it from one of those clients.
132
+
133
+ ## License
134
+
135
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ // Published CLI launcher. The real CLI is the built bundle at dist/app/cli.js
3
+ // (produced by scripts/build-js.mjs at publish time). This thin shim only exists
4
+ // so the package has a bin/ dir; importing the bundle runs its dispatch().
5
+ import '../dist/app/cli.js';
@@ -0,0 +1,21 @@
1
+ {
2
+ "_comment": "Optional config file: a flat JSON fallback BELOW environment variables. Copy to config.json (gitignored) and fill in. Precedence: CLI flags > real ENV > .env > config.json > built-in defaults. Keys mirror .env.example exactly. The server refuses to start with no auth source (CODEIUM_API_KEY / CODEIUM_AUTH_TOKEN / CODEIUM_EMAIL+CODEIUM_PASSWORD / a non-empty accounts.json) unless WINDSURFAPI_ALLOW_NO_AUTH=1.",
3
+
4
+ "PORT": "3003",
5
+ "HOST": "0.0.0.0",
6
+ "API_KEY": "",
7
+ "DATA_DIR": "",
8
+
9
+ "CODEIUM_API_KEY": "",
10
+ "CODEIUM_AUTH_TOKEN": "",
11
+
12
+ "LS_BINARY_PATH": "/opt/windsurf/language_server_linux_x64",
13
+ "LS_PORT": "42100",
14
+
15
+ "DASHBOARD_PASSWORD": "",
16
+
17
+ "DEFAULT_MODEL": "claude-4.5-sonnet-thinking",
18
+ "MAX_TOKENS": "8192",
19
+ "LOG_LEVEL": "info",
20
+ "ALLOW_PRIVATE_PROXY_HOSTS": ""
21
+ }