copilot-cursor-proxy 1.0.1 → 1.0.2
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/README.md +52 -38
- package/auth-config.ts +61 -0
- package/dashboard.html +814 -270
- package/package.json +2 -2
- package/proxy-router.ts +213 -4
- package/responses-converters.ts +3 -3
- package/stream-proxy.ts +32 -1
- package/usage-db.ts +210 -0
package/README.md
CHANGED
|
@@ -81,30 +81,32 @@ Cursor → (HTTPS tunnel) → proxy-router (:4142) → copilot-api (:4141) → G
|
|
|
81
81
|
|
|
82
82
|
> **💡 Tip:** Visit the [Dashboard](http://localhost:4142) to see all available models and copy their IDs.
|
|
83
83
|
|
|
84
|
-
### Tested Models (
|
|
84
|
+
### Tested Models (15/21 passing)
|
|
85
85
|
|
|
86
|
-
| Cursor Model Name | Actual Model |
|
|
86
|
+
| Cursor Model Name | Actual Model | Status |
|
|
87
87
|
|---|---|---|
|
|
88
|
-
| `cus-gpt-4o` | GPT-4o |
|
|
89
|
-
| `cus-gpt-4.1` | GPT-4.1 |
|
|
90
|
-
| `cus-gpt-5-mini` | GPT-5 Mini |
|
|
91
|
-
| `cus-gpt-5.1` | GPT-5.1 |
|
|
92
|
-
| `cus-gpt-5.2` | GPT-5.2 |
|
|
93
|
-
| `cus-gpt-5.2-codex` | GPT-5.2 Codex |
|
|
94
|
-
| `cus-gpt-5.3-codex` | GPT-5.3 Codex |
|
|
95
|
-
| `cus-gpt-5.4` | GPT-5.4 |
|
|
96
|
-
| `cus-gpt-5.4-mini` | GPT-5.4 Mini |
|
|
97
|
-
| `cus-
|
|
98
|
-
| `cus-claude-
|
|
99
|
-
| `cus-claude-sonnet-4
|
|
100
|
-
| `cus-claude-sonnet-4.
|
|
101
|
-
| `cus-claude-
|
|
102
|
-
| `cus-claude-opus-4.
|
|
103
|
-
| `cus-claude-opus-4.6
|
|
104
|
-
| `cus-
|
|
105
|
-
| `cus-gemini-
|
|
106
|
-
| `cus-gemini-3
|
|
107
|
-
| `cus-
|
|
88
|
+
| `cus-gpt-4o` | GPT-4o | ✅ |
|
|
89
|
+
| `cus-gpt-4.1` | GPT-4.1 | ✅ |
|
|
90
|
+
| `cus-gpt-5-mini` | GPT-5 Mini | ✅ |
|
|
91
|
+
| `cus-gpt-5.1` | GPT-5.1 | ✅ |
|
|
92
|
+
| `cus-gpt-5.2` | GPT-5.2 | ⚠️ See note |
|
|
93
|
+
| `cus-gpt-5.2-codex` | GPT-5.2 Codex | ⚠️ See note |
|
|
94
|
+
| `cus-gpt-5.3-codex` | GPT-5.3 Codex | ⚠️ See note |
|
|
95
|
+
| `cus-gpt-5.4` | GPT-5.4 | ⚠️ See note |
|
|
96
|
+
| `cus-gpt-5.4-mini` | GPT-5.4 Mini | ⚠️ See note |
|
|
97
|
+
| `cus-goldeneye` | Goldeneye | ⚠️ See note |
|
|
98
|
+
| `cus-claude-haiku-4.5` | Claude Haiku 4.5 | ✅ |
|
|
99
|
+
| `cus-claude-sonnet-4` | Claude Sonnet 4 | ✅ |
|
|
100
|
+
| `cus-claude-sonnet-4.5` | Claude Sonnet 4.5 | ✅ |
|
|
101
|
+
| `cus-claude-sonnet-4.6` | Claude Sonnet 4.6 | ✅ |
|
|
102
|
+
| `cus-claude-opus-4.5` | Claude Opus 4.5 | ✅ |
|
|
103
|
+
| `cus-claude-opus-4.6` | Claude Opus 4.6 | ✅ |
|
|
104
|
+
| `cus-claude-opus-4.6-1m` | Claude Opus 4.6 (1M) | ✅ |
|
|
105
|
+
| `cus-gemini-2.5-pro` | Gemini 2.5 Pro | ✅ |
|
|
106
|
+
| `cus-gemini-3-flash-preview` | Gemini 3 Flash | ✅ |
|
|
107
|
+
| `cus-gemini-3.1-pro-preview` | Gemini 3.1 Pro | ✅ |
|
|
108
|
+
|
|
109
|
+
> **⚠️ GPT-5.2+, GPT-5.x-codex, and goldeneye** are currently broken. These models require the `/v1/responses` API or `max_completion_tokens` instead of `max_tokens`, but `copilot-api` injects `max_tokens` into all requests. The proxy has a Responses API bridge built in, but `copilot-api` no longer exposes the `/v1/responses` endpoint. This will be resolved when `copilot-api` is updated. **All Claude, Gemini, GPT-4.x, GPT-5-mini, and GPT-5.1 models work fine.**
|
|
108
110
|
|
|
109
111
|

|
|
110
112
|
|
|
@@ -125,8 +127,8 @@ Cursor → (HTTPS tunnel) → proxy-router (:4142) → copilot-api (:4141) → G
|
|
|
125
127
|
| `thinking` / `cache_control` blocks | Stripped |
|
|
126
128
|
| `metadata` / `anthropic_version` | Stripped |
|
|
127
129
|
| Images in Claude requests | `[Image Omitted]` placeholder |
|
|
128
|
-
| GPT-5.x
|
|
129
|
-
| Responses API
|
|
130
|
+
| GPT-5.x `max_tokens` | Converted to `max_completion_tokens` |
|
|
131
|
+
| GPT-5.x Responses API | **Bridge built in** (needs `copilot-api` support) |
|
|
130
132
|
|
|
131
133
|
### Supported Workflows
|
|
132
134
|
|
|
@@ -140,23 +142,35 @@ Cursor → (HTTPS tunnel) → proxy-router (:4142) → copilot-api (:4141) → G
|
|
|
140
142
|
|
|
141
143
|
---
|
|
142
144
|
|
|
143
|
-
## 🔒 Security
|
|
145
|
+
## 🔒 Security
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
### Dashboard Password
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
- Linux/macOS: `~/.local/share/copilot-api/config.json`
|
|
149
|
-
- Windows: `%USERPROFILE%\.local\share\copilot-api\config.json`
|
|
149
|
+
The dashboard is password-protected. On first visit, set a password to prevent unauthorized access.
|
|
150
150
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
151
|
+
### API Key Management
|
|
152
|
+
|
|
153
|
+
Manage API keys directly from the **Endpoint** tab in the dashboard:
|
|
154
|
+
|
|
155
|
+
1. Toggle **"Require API Key"** to enable authentication
|
|
156
|
+
2. Click **"+ Create Key"** to generate a new `cpk-xxx` key
|
|
157
|
+
3. Copy the key (shown only once!) and paste it into Cursor's **API Key** field
|
|
158
|
+
4. Enable/disable or delete keys as needed
|
|
159
|
+
|
|
160
|
+
When enabled, all `/v1/*` requests must include `Authorization: Bearer <your-key>`.
|
|
161
|
+
|
|
162
|
+

|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## 📊 Dashboard
|
|
167
|
+
|
|
168
|
+
Access the dashboard at **[http://localhost:4142](http://localhost:4142)**
|
|
158
169
|
|
|
159
|
-
|
|
170
|
+
Three tabs:
|
|
171
|
+
- **Endpoint** — Proxy URL, API key management, model list
|
|
172
|
+
- **Usage** — Request stats, token counts, per-model breakdown, recent requests
|
|
173
|
+
- **Console Log** — Real-time proxy logs with color-coded levels
|
|
160
174
|
|
|
161
175
|
---
|
|
162
176
|
|
|
@@ -168,7 +182,7 @@ Then use the same key as the **API Key** in Cursor settings.
|
|
|
168
182
|
| Streaming | ✅ Works |
|
|
169
183
|
| Plan mode | ✅ Works |
|
|
170
184
|
| Agent mode | ✅ Works |
|
|
171
|
-
| GPT-5.x models |
|
|
185
|
+
| GPT-5.x models | ⚠️ Blocked by copilot-api `max_tokens` bug |
|
|
172
186
|
| Extended thinking (chain-of-thought) | ❌ Stripped |
|
|
173
187
|
| Prompt caching (`cache_control`) | ❌ Stripped |
|
|
174
188
|
| Claude Vision | ❌ Not supported via Copilot |
|
package/auth-config.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
2
|
+
import { homedir } from 'os';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
export interface ApiKey {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
key: string;
|
|
9
|
+
active: boolean;
|
|
10
|
+
createdAt: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface AuthConfig {
|
|
14
|
+
requireApiKey: boolean;
|
|
15
|
+
keys: ApiKey[];
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CONFIG_DIR = join(homedir(), '.copilot-proxy');
|
|
19
|
+
const CONFIG_PATH = join(CONFIG_DIR, 'auth.json');
|
|
20
|
+
|
|
21
|
+
const DEFAULT_CONFIG: AuthConfig = { requireApiKey: false, keys: [] };
|
|
22
|
+
|
|
23
|
+
export function loadAuthConfig(): AuthConfig {
|
|
24
|
+
try {
|
|
25
|
+
if (!existsSync(CONFIG_PATH)) return { ...DEFAULT_CONFIG, keys: [] };
|
|
26
|
+
const raw = readFileSync(CONFIG_PATH, 'utf-8');
|
|
27
|
+
const parsed = JSON.parse(raw);
|
|
28
|
+
return {
|
|
29
|
+
requireApiKey: !!parsed.requireApiKey,
|
|
30
|
+
keys: Array.isArray(parsed.keys) ? parsed.keys : [],
|
|
31
|
+
};
|
|
32
|
+
} catch {
|
|
33
|
+
return { ...DEFAULT_CONFIG, keys: [] };
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function saveAuthConfig(config: AuthConfig): void {
|
|
38
|
+
if (!existsSync(CONFIG_DIR)) mkdirSync(CONFIG_DIR, { recursive: true });
|
|
39
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf-8');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function randomHex(bytes: number): string {
|
|
43
|
+
const arr = new Uint8Array(bytes);
|
|
44
|
+
crypto.getRandomValues(arr);
|
|
45
|
+
return Array.from(arr, b => b.toString(16).padStart(2, '0')).join('');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function generateApiKey(name: string): ApiKey {
|
|
49
|
+
return {
|
|
50
|
+
id: randomHex(4), // 8-char hex
|
|
51
|
+
name,
|
|
52
|
+
key: 'cpk-' + randomHex(16), // cpk- + 32 hex chars
|
|
53
|
+
active: true,
|
|
54
|
+
createdAt: Date.now(),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function validateApiKey(key: string): boolean {
|
|
59
|
+
const config = loadAuthConfig();
|
|
60
|
+
return config.keys.some(k => k.key === key && k.active);
|
|
61
|
+
}
|