cursor-agent-bridge 0.1.4 → 0.1.6
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 +65 -25
- package/dist/cli.mjs +170 -7
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +1 -1
- package/dist/{server-Bk7ol2lA.mjs → server-BtOiVsUV.mjs} +8 -4
- package/package.json +3 -2
- package/dist/cli.mjs.map +0 -1
- package/dist/index.d.mts.map +0 -1
- package/dist/server-Bk7ol2lA.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
OpenAI-compatible HTTP bridge for the Cursor Agent CLI.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Responses API
|
|
5
|
+
Use it when you want Codex or another OpenAI-style client to call your local
|
|
6
|
+
Cursor Agent CLI through `http://127.0.0.1:4646/v1`. The bridge supports the
|
|
7
|
+
Responses API that Codex custom providers use, plus Chat Completions for simpler
|
|
8
8
|
clients.
|
|
9
9
|
|
|
10
10
|
## Requirements
|
|
@@ -23,11 +23,19 @@ agent --list-models
|
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
26
|
-
Install the package globally, then confirm the
|
|
26
|
+
Install the package globally, then confirm the CLI is on your `PATH`:
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
29
|
pnpm add -g cursor-agent-bridge
|
|
30
|
-
|
|
30
|
+
cab --version
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The package installs two commands. `cab` is the short alias; the full
|
|
34
|
+
`cursor-agent-bridge` command stays available for scripts and existing setups.
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cab serve
|
|
38
|
+
cab config switch cursor
|
|
31
39
|
```
|
|
32
40
|
|
|
33
41
|
For local development:
|
|
@@ -35,7 +43,7 @@ For local development:
|
|
|
35
43
|
```bash
|
|
36
44
|
pnpm install
|
|
37
45
|
pnpm build
|
|
38
|
-
|
|
46
|
+
node dist/cli.mjs serve
|
|
39
47
|
```
|
|
40
48
|
|
|
41
49
|
## Upgrade
|
|
@@ -43,20 +51,20 @@ pnpm exec cursor-agent-bridge serve
|
|
|
43
51
|
Check for updates:
|
|
44
52
|
|
|
45
53
|
```bash
|
|
46
|
-
|
|
54
|
+
cab upgrade --check
|
|
47
55
|
```
|
|
48
56
|
|
|
49
57
|
Install the latest published version:
|
|
50
58
|
|
|
51
59
|
```bash
|
|
52
|
-
|
|
60
|
+
cab upgrade
|
|
53
61
|
```
|
|
54
62
|
|
|
55
63
|
Options:
|
|
56
64
|
|
|
57
65
|
```bash
|
|
58
|
-
|
|
59
|
-
|
|
66
|
+
cab upgrade --target 0.1.3
|
|
67
|
+
cab upgrade --manager npm
|
|
60
68
|
```
|
|
61
69
|
|
|
62
70
|
`--check` compares your installed version with npm and exits `1` when a newer
|
|
@@ -67,7 +75,7 @@ If you use the optional macOS LaunchAgent, reinstall it after upgrading so the
|
|
|
67
75
|
service picks up the new binary:
|
|
68
76
|
|
|
69
77
|
```bash
|
|
70
|
-
|
|
78
|
+
cab launch-agent install
|
|
71
79
|
```
|
|
72
80
|
|
|
73
81
|
For local development from this repository, use `git pull`, `pnpm install`, and
|
|
@@ -78,7 +86,7 @@ For local development from this repository, use `git pull`, `pnpm install`, and
|
|
|
78
86
|
Run the bridge in the foreground:
|
|
79
87
|
|
|
80
88
|
```bash
|
|
81
|
-
|
|
89
|
+
cab serve --host 127.0.0.1 --port 4646
|
|
82
90
|
```
|
|
83
91
|
|
|
84
92
|
Configuration:
|
|
@@ -105,37 +113,37 @@ processes. On macOS, you can install the optional LaunchAgent to start the
|
|
|
105
113
|
bridge at login and restart it after crashes:
|
|
106
114
|
|
|
107
115
|
```bash
|
|
108
|
-
|
|
116
|
+
cab launch-agent install
|
|
109
117
|
```
|
|
110
118
|
|
|
111
119
|
Manage the service:
|
|
112
120
|
|
|
113
121
|
```bash
|
|
114
|
-
|
|
115
|
-
|
|
122
|
+
cab launch-agent status
|
|
123
|
+
cab launch-agent uninstall
|
|
116
124
|
```
|
|
117
125
|
|
|
118
126
|
The LaunchAgent listens on `127.0.0.1:4646` by default. Skip it if you prefer to
|
|
119
|
-
run `
|
|
127
|
+
run `cab serve` yourself before starting Codex.
|
|
120
128
|
|
|
121
129
|
## Codex Config
|
|
122
130
|
|
|
123
|
-
|
|
131
|
+
For Codex CLI profile usage, create or update `~/.codex/cursor.config.toml`:
|
|
124
132
|
|
|
125
133
|
```bash
|
|
126
|
-
|
|
134
|
+
cab config write
|
|
127
135
|
```
|
|
128
136
|
|
|
129
137
|
Preview the generated profile without writing a file:
|
|
130
138
|
|
|
131
139
|
```bash
|
|
132
|
-
|
|
140
|
+
cab config print
|
|
133
141
|
```
|
|
134
142
|
|
|
135
143
|
Validate an existing profile:
|
|
136
144
|
|
|
137
145
|
```bash
|
|
138
|
-
|
|
146
|
+
cab config check
|
|
139
147
|
```
|
|
140
148
|
|
|
141
149
|
The generated profile looks like this:
|
|
@@ -159,19 +167,51 @@ codex --profile cursor
|
|
|
159
167
|
Use `/model` in Codex to pick a Cursor model. The model catalog comes from
|
|
160
168
|
`agent --list-models`.
|
|
161
169
|
|
|
170
|
+
## Codex IDE Switching
|
|
171
|
+
|
|
172
|
+
The Codex IDE extension reads the user-level `~/.codex/config.toml`. Switch
|
|
173
|
+
that file when you want the IDE to use Cursor Agent Bridge:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
cab config switch cursor
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Switch back to Codex's default provider:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
cab config switch openai
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Check the active provider:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
cab config switch status
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The switch command backs up the previous `~/.codex/config.toml` to
|
|
192
|
+
`~/.codex/config.toml.bak.cursor-agent-bridge` before enabling Cursor. Restore
|
|
193
|
+
that backup with:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
cab config switch restore
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Reload the Codex IDE window or start a new session after switching. Codex does
|
|
200
|
+
not reliably hot-reload provider changes while a session is running.
|
|
201
|
+
|
|
162
202
|
## Troubleshooting
|
|
163
203
|
|
|
164
204
|
Run a full preflight before starting Codex:
|
|
165
205
|
|
|
166
206
|
```bash
|
|
167
|
-
|
|
207
|
+
cab doctor
|
|
168
208
|
```
|
|
169
209
|
|
|
170
210
|
List available Cursor models without starting the HTTP server:
|
|
171
211
|
|
|
172
212
|
```bash
|
|
173
|
-
|
|
174
|
-
|
|
213
|
+
cab models
|
|
214
|
+
cab models --json
|
|
175
215
|
```
|
|
176
216
|
|
|
177
217
|
If `config write` finds a different `model_provider`, pass `--force` to switch
|
|
@@ -187,8 +227,8 @@ POST /v1/chat/completions
|
|
|
187
227
|
```
|
|
188
228
|
|
|
189
229
|
`GET /v1/models` returns an OpenAI-style model list by default. When Codex calls
|
|
190
|
-
the same endpoint
|
|
191
|
-
|
|
230
|
+
the same endpoint, the bridge returns the catalog shape Codex expects for the
|
|
231
|
+
model selector.
|
|
192
232
|
|
|
193
233
|
Model lists are cached briefly so the bridge does not spawn
|
|
194
234
|
`agent --list-models` for every request. Pass `refresh=1` to force a refresh.
|
package/dist/cli.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { i as CursorRunner, n as engines, r as version, s as toOpenAIModelList, t as startServer } from "./server-
|
|
2
|
+
import { i as CursorRunner, n as engines, r as version, s as toOpenAIModelList, t as startServer } from "./server-BtOiVsUV.mjs";
|
|
3
3
|
import { execFile, execFileSync, spawn } from "node:child_process";
|
|
4
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
4
|
+
import { copyFile, mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
5
5
|
import { homedir } from "node:os";
|
|
6
6
|
import { dirname, join, resolve } from "node:path";
|
|
7
7
|
import { promisify } from "node:util";
|
|
@@ -29,10 +29,19 @@ function readHostAndPort(defaultHost = "127.0.0.1", defaultPort = 4646) {
|
|
|
29
29
|
//#endregion
|
|
30
30
|
//#region src/codex-config.ts
|
|
31
31
|
const DEFAULT_CODEX_PROFILE = "cursor";
|
|
32
|
+
const OPENAI_PROVIDER = "openai";
|
|
33
|
+
const USER_CODEX_CONFIG_FILE = "config.toml";
|
|
34
|
+
const SWITCH_BACKUP_SUFFIX = ".bak.cursor-agent-bridge";
|
|
32
35
|
function resolveCodexConfigPath(profile = DEFAULT_CODEX_PROFILE, homeDir = homedir()) {
|
|
33
36
|
assertValidProfile(profile);
|
|
34
37
|
return join(homeDir, ".codex", `${profile}.config.toml`);
|
|
35
38
|
}
|
|
39
|
+
function resolveCodexUserConfigPath(homeDir = homedir()) {
|
|
40
|
+
return join(homeDir, ".codex", USER_CODEX_CONFIG_FILE);
|
|
41
|
+
}
|
|
42
|
+
function resolveCodexSwitchBackupPath(filePath) {
|
|
43
|
+
return `${filePath}${SWITCH_BACKUP_SUFFIX}`;
|
|
44
|
+
}
|
|
36
45
|
function buildBaseUrl(host, port) {
|
|
37
46
|
return `http://${host}:${port}/v1`;
|
|
38
47
|
}
|
|
@@ -64,7 +73,7 @@ function parseCodexConfig(content, profile = DEFAULT_CODEX_PROFILE) {
|
|
|
64
73
|
}
|
|
65
74
|
const assignment = line.match(/^([A-Za-z0-9_.-]+)\s*=\s*(.+)$/);
|
|
66
75
|
if (!assignment) continue;
|
|
67
|
-
const key = assignment[1]
|
|
76
|
+
const key = assignment[1];
|
|
68
77
|
const value = parseTomlValue(assignment[2] ?? "");
|
|
69
78
|
if (section === providerSection) {
|
|
70
79
|
if (key === "name") fields.providerName = value;
|
|
@@ -121,6 +130,86 @@ async function writeCodexConfig(options) {
|
|
|
121
130
|
updated: true
|
|
122
131
|
};
|
|
123
132
|
}
|
|
133
|
+
async function getCodexProviderStatus(filePath) {
|
|
134
|
+
const content = await readCodexConfigIfExists(filePath);
|
|
135
|
+
return content === void 0 ? {
|
|
136
|
+
path: filePath,
|
|
137
|
+
exists: false,
|
|
138
|
+
modelProvider: void 0
|
|
139
|
+
} : {
|
|
140
|
+
path: filePath,
|
|
141
|
+
exists: true,
|
|
142
|
+
modelProvider: parseCodexConfig(content).modelProvider
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
async function switchCodexProvider(options) {
|
|
146
|
+
const existing = await readCodexConfigIfExists(options.filePath);
|
|
147
|
+
const backupPath = resolveCodexSwitchBackupPath(options.filePath);
|
|
148
|
+
if (options.mode === "cursor") {
|
|
149
|
+
await mkdir(dirname(options.filePath), { recursive: true });
|
|
150
|
+
const existingProvider = existing === void 0 ? void 0 : parseCodexConfig(existing).modelProvider;
|
|
151
|
+
if (existing !== void 0 && existingProvider !== "cursor") await copyFile(options.filePath, backupPath);
|
|
152
|
+
const merged = existing === void 0 ? {
|
|
153
|
+
content: buildCodexConfigToml(options),
|
|
154
|
+
changed: true
|
|
155
|
+
} : mergeCodexConfig(existing, {
|
|
156
|
+
...options,
|
|
157
|
+
force: true
|
|
158
|
+
});
|
|
159
|
+
if ("error" in merged) throw new Error(merged.error);
|
|
160
|
+
if (!merged.changed && existing !== void 0) return {
|
|
161
|
+
path: options.filePath,
|
|
162
|
+
mode: "cursor",
|
|
163
|
+
changed: false,
|
|
164
|
+
...existingProvider !== "cursor" && existing !== void 0 ? { backupPath } : {}
|
|
165
|
+
};
|
|
166
|
+
await writeFileAtomic(options.filePath, merged.content);
|
|
167
|
+
return {
|
|
168
|
+
path: options.filePath,
|
|
169
|
+
mode: "cursor",
|
|
170
|
+
changed: true,
|
|
171
|
+
...existingProvider !== "cursor" && existing !== void 0 ? { backupPath } : {}
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const backup = await readCodexConfigIfExists(backupPath);
|
|
175
|
+
if (backup !== void 0) {
|
|
176
|
+
await writeFileAtomic(options.filePath, backup);
|
|
177
|
+
return {
|
|
178
|
+
path: options.filePath,
|
|
179
|
+
mode: OPENAI_PROVIDER,
|
|
180
|
+
changed: normalizeToml(existing ?? "") !== normalizeToml(backup),
|
|
181
|
+
backupPath,
|
|
182
|
+
restoredBackup: true
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const content = removeCursorProviderSelection(existing ?? "");
|
|
186
|
+
if (normalizeToml(content) === normalizeToml(existing ?? "")) return {
|
|
187
|
+
path: options.filePath,
|
|
188
|
+
mode: OPENAI_PROVIDER,
|
|
189
|
+
changed: false,
|
|
190
|
+
restoredBackup: false
|
|
191
|
+
};
|
|
192
|
+
await mkdir(dirname(options.filePath), { recursive: true });
|
|
193
|
+
await writeFileAtomic(options.filePath, content);
|
|
194
|
+
return {
|
|
195
|
+
path: options.filePath,
|
|
196
|
+
mode: OPENAI_PROVIDER,
|
|
197
|
+
changed: true,
|
|
198
|
+
restoredBackup: false
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
async function restoreCodexProviderBackup(filePath) {
|
|
202
|
+
const backupPath = resolveCodexSwitchBackupPath(filePath);
|
|
203
|
+
const backup = await readCodexConfigIfExists(backupPath);
|
|
204
|
+
if (backup === void 0) throw new Error(`No switch backup found at ${backupPath}`);
|
|
205
|
+
const existing = await readCodexConfigIfExists(filePath);
|
|
206
|
+
await writeFileAtomic(filePath, backup);
|
|
207
|
+
return {
|
|
208
|
+
path: filePath,
|
|
209
|
+
backupPath,
|
|
210
|
+
changed: normalizeToml(existing ?? "") !== normalizeToml(backup)
|
|
211
|
+
};
|
|
212
|
+
}
|
|
124
213
|
function mergeCodexConfig(existing, options) {
|
|
125
214
|
const profile = options.profile ?? "cursor";
|
|
126
215
|
assertValidProfile(profile);
|
|
@@ -206,6 +295,44 @@ function mergeCodexConfig(existing, options) {
|
|
|
206
295
|
if (!handledProviderKeys.has("wire_api")) output.push("wire_api = \"responses\"");
|
|
207
296
|
}
|
|
208
297
|
}
|
|
298
|
+
async function readCodexConfigIfExists(filePath) {
|
|
299
|
+
try {
|
|
300
|
+
return await readFile(filePath, "utf8");
|
|
301
|
+
} catch (error) {
|
|
302
|
+
if (error.code !== "ENOENT") throw error;
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
async function writeFileAtomic(filePath, content) {
|
|
307
|
+
await mkdir(dirname(filePath), { recursive: true });
|
|
308
|
+
const tmpPath = `${filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
309
|
+
await writeFile(tmpPath, content, "utf8");
|
|
310
|
+
await rename(tmpPath, filePath);
|
|
311
|
+
}
|
|
312
|
+
function removeCursorProviderSelection(existing) {
|
|
313
|
+
const lines = existing.split("\n");
|
|
314
|
+
const output = [];
|
|
315
|
+
let section = "";
|
|
316
|
+
for (const rawLine of lines) {
|
|
317
|
+
const trimmed = rawLine.trim();
|
|
318
|
+
const sectionMatch = trimmed.match(/^\[(.+)\]$/);
|
|
319
|
+
if (sectionMatch) {
|
|
320
|
+
section = sectionMatch[1];
|
|
321
|
+
output.push(rawLine);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
const assignment = trimmed.match(/^([A-Za-z0-9_.-]+)\s*=\s*(.+)$/);
|
|
325
|
+
if (!section && assignment) {
|
|
326
|
+
const key = assignment[1];
|
|
327
|
+
const value = parseTomlValue(assignment[2]);
|
|
328
|
+
if (key === "model_provider" && value === "cursor") continue;
|
|
329
|
+
if (key === "model" && value === "auto") continue;
|
|
330
|
+
}
|
|
331
|
+
output.push(rawLine);
|
|
332
|
+
}
|
|
333
|
+
const content = output.join("\n").trimEnd();
|
|
334
|
+
return content ? `${content}\n` : "";
|
|
335
|
+
}
|
|
209
336
|
function assertValidProfile(profile) {
|
|
210
337
|
if (/^[A-Za-z0-9_-]+$/.test(profile)) return;
|
|
211
338
|
throw new Error("Invalid Codex profile. Use only letters, numbers, underscores, or hyphens.");
|
|
@@ -223,7 +350,7 @@ function parseTomlValue(raw) {
|
|
|
223
350
|
return trimmed;
|
|
224
351
|
}
|
|
225
352
|
function unescapeTomlString(value) {
|
|
226
|
-
|
|
353
|
+
const escapes = {
|
|
227
354
|
"\"": "\"",
|
|
228
355
|
"\\": "\\",
|
|
229
356
|
b: "\b",
|
|
@@ -231,7 +358,8 @@ function unescapeTomlString(value) {
|
|
|
231
358
|
n: "\n",
|
|
232
359
|
f: "\f",
|
|
233
360
|
r: "\r"
|
|
234
|
-
}
|
|
361
|
+
};
|
|
362
|
+
return value.replace(/\\(["\\btnfr])/g, (_match, escaped) => escapes[escaped]);
|
|
235
363
|
}
|
|
236
364
|
function stripInlineTomlComment(raw) {
|
|
237
365
|
let quote;
|
|
@@ -690,12 +818,16 @@ Usage:
|
|
|
690
818
|
cursor-agent-bridge config print [--host 127.0.0.1] [--port 4646] [--profile cursor]
|
|
691
819
|
cursor-agent-bridge config check [--file ~/.codex/cursor.config.toml] [--host 127.0.0.1] [--port 4646] [--profile cursor]
|
|
692
820
|
cursor-agent-bridge config write [--file ~/.codex/cursor.config.toml] [--host 127.0.0.1] [--port 4646] [--profile cursor] [--force]
|
|
821
|
+
cursor-agent-bridge config switch cursor|openai|status|restore [--file ~/.codex/config.toml] [--host 127.0.0.1] [--port 4646]
|
|
693
822
|
cursor-agent-bridge models [--json] [--refresh]
|
|
694
823
|
cursor-agent-bridge launch-agent install [--host 127.0.0.1] [--port 4646] [--agent-path agent]
|
|
695
824
|
cursor-agent-bridge launch-agent uninstall
|
|
696
825
|
cursor-agent-bridge launch-agent status
|
|
697
826
|
cursor-agent-bridge upgrade [--check] [--target latest] [--manager auto|npm|pnpm]
|
|
698
827
|
|
|
828
|
+
Alias:
|
|
829
|
+
cab is the short alias for cursor-agent-bridge
|
|
830
|
+
|
|
699
831
|
Environment:
|
|
700
832
|
HOST Listen host, default 127.0.0.1
|
|
701
833
|
PORT Listen port, default 4646
|
|
@@ -783,6 +915,39 @@ if (command === "config") {
|
|
|
783
915
|
console.log(`Start Codex with: codex --profile ${profile}`);
|
|
784
916
|
process.exit(0);
|
|
785
917
|
}
|
|
918
|
+
if (action === "switch") {
|
|
919
|
+
const mode = process.argv[4] ?? "status";
|
|
920
|
+
const switchFilePath = readArg("--file", void 0) ?? resolveCodexUserConfigPath();
|
|
921
|
+
if (mode === "status") {
|
|
922
|
+
const status = await getCodexProviderStatus(switchFilePath);
|
|
923
|
+
const provider = status.modelProvider ?? "default";
|
|
924
|
+
console.log(`Codex config: ${status.path}`);
|
|
925
|
+
console.log(status.exists ? `Current model_provider: ${provider}` : "Current model_provider: default (config file not found)");
|
|
926
|
+
console.log(`Switch backup: ${resolveCodexSwitchBackupPath(status.path)}`);
|
|
927
|
+
process.exit(0);
|
|
928
|
+
}
|
|
929
|
+
if (mode === "restore") {
|
|
930
|
+
const result = await restoreCodexProviderBackup(switchFilePath);
|
|
931
|
+
console.log(result.changed ? `Restored Codex config from ${result.backupPath}` : `Codex config already matches ${result.backupPath}`);
|
|
932
|
+
console.log("Reload Codex IDE or start a new session to apply it.");
|
|
933
|
+
process.exit(0);
|
|
934
|
+
}
|
|
935
|
+
if (mode !== "cursor" && mode !== "openai") {
|
|
936
|
+
console.error("Unknown config switch target. Use cursor, openai, status, or restore.");
|
|
937
|
+
process.exit(1);
|
|
938
|
+
}
|
|
939
|
+
const result = await switchCodexProvider({
|
|
940
|
+
filePath: switchFilePath,
|
|
941
|
+
host,
|
|
942
|
+
port,
|
|
943
|
+
mode
|
|
944
|
+
});
|
|
945
|
+
console.log(result.changed ? `Switched Codex config to ${mode}: ${result.path}` : `Codex config already uses ${mode}: ${result.path}`);
|
|
946
|
+
if (result.backupPath) console.log(`Backup: ${result.backupPath}`);
|
|
947
|
+
if (mode === "cursor") console.log(`Make sure the bridge is running: cursor-agent-bridge serve --host ${host} --port ${port}`);
|
|
948
|
+
console.log("Reload Codex IDE or start a new session to apply it.");
|
|
949
|
+
process.exit(0);
|
|
950
|
+
}
|
|
786
951
|
} catch (error) {
|
|
787
952
|
console.error(error instanceof Error ? error.message : String(error));
|
|
788
953
|
process.exit(1);
|
|
@@ -861,5 +1026,3 @@ process.on("SIGINT", shutdown);
|
|
|
861
1026
|
process.on("SIGTERM", shutdown);
|
|
862
1027
|
//#endregion
|
|
863
1028
|
export {};
|
|
864
|
-
|
|
865
|
-
//# sourceMappingURL=cli.mjs.map
|
package/dist/index.d.mts
CHANGED
|
@@ -143,5 +143,4 @@ declare class CursorRunner {
|
|
|
143
143
|
//#region src/server.d.ts
|
|
144
144
|
declare function startServer(config?: ServerConfig): Promise<http.Server<typeof http.IncomingMessage, typeof http.ServerResponse>>;
|
|
145
145
|
//#endregion
|
|
146
|
-
export { type BridgeModel, type ChatCompletionRequest, type ChatMessage, type ChatRole, type CursorRunEvents, type CursorRunOptions, type CursorRunResult, CursorRunner, type ResponsesRequest, type ServerConfig, messagesToPrompt, normalizeModel, parseAgentModelList, responsesToMessages, startServer, toCodexModelCatalog, toOpenAIModelList };
|
|
147
|
-
//# sourceMappingURL=index.d.mts.map
|
|
146
|
+
export { type BridgeModel, type ChatCompletionRequest, type ChatMessage, type ChatRole, type CursorRunEvents, type CursorRunOptions, type CursorRunResult, CursorRunner, type ResponsesRequest, type ServerConfig, messagesToPrompt, normalizeModel, parseAgentModelList, responsesToMessages, startServer, toCodexModelCatalog, toOpenAIModelList };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as parseAgentModelList, c as messagesToPrompt, i as CursorRunner, l as normalizeModel, o as toCodexModelCatalog, s as toOpenAIModelList, t as startServer, u as responsesToMessages } from "./server-
|
|
1
|
+
import { a as parseAgentModelList, c as messagesToPrompt, i as CursorRunner, l as normalizeModel, o as toCodexModelCatalog, s as toOpenAIModelList, t as startServer, u as responsesToMessages } from "./server-BtOiVsUV.mjs";
|
|
2
2
|
export { CursorRunner, messagesToPrompt, normalizeModel, parseAgentModelList, responsesToMessages, startServer, toCodexModelCatalog, toOpenAIModelList };
|
|
@@ -328,7 +328,7 @@ function extractAssistantText(message) {
|
|
|
328
328
|
}
|
|
329
329
|
//#endregion
|
|
330
330
|
//#region package.json
|
|
331
|
-
var version = "0.1.
|
|
331
|
+
var version = "0.1.6";
|
|
332
332
|
var engines = { "node": ">=22.13" };
|
|
333
333
|
//#endregion
|
|
334
334
|
//#region src/adapter/openai.ts
|
|
@@ -541,7 +541,7 @@ async function route(req, res, runner, maxBodyBytes) {
|
|
|
541
541
|
}
|
|
542
542
|
if (req.method === "GET" && url.pathname === "/v1/models") {
|
|
543
543
|
const models = await runner.listModels({ refresh: url.searchParams.get("refresh") === "1" });
|
|
544
|
-
sendJson(res, 200,
|
|
544
|
+
sendJson(res, 200, shouldReturnCodexModelCatalog(req, url) ? toCodexModelCatalog(models) : toOpenAIModelList(models));
|
|
545
545
|
return;
|
|
546
546
|
}
|
|
547
547
|
if (req.method === "POST" && url.pathname === "/v1/chat/completions") {
|
|
@@ -558,6 +558,12 @@ async function route(req, res, runner, maxBodyBytes) {
|
|
|
558
558
|
code: "not_found"
|
|
559
559
|
} });
|
|
560
560
|
}
|
|
561
|
+
function shouldReturnCodexModelCatalog(req, url) {
|
|
562
|
+
if (url.searchParams.has("client_version")) return true;
|
|
563
|
+
if (url.searchParams.get("format") === "codex") return true;
|
|
564
|
+
const userAgent = req.headers["user-agent"];
|
|
565
|
+
return typeof userAgent === "string" && /\bCodex\b/i.test(userAgent);
|
|
566
|
+
}
|
|
561
567
|
async function handleChat(req, res, runner, maxBodyBytes) {
|
|
562
568
|
const body = await readJson(req, maxBodyBytes);
|
|
563
569
|
if (!Array.isArray(body.messages) || body.messages.length === 0) {
|
|
@@ -745,5 +751,3 @@ function sendJson(res, status, value) {
|
|
|
745
751
|
}
|
|
746
752
|
//#endregion
|
|
747
753
|
export { parseAgentModelList as a, messagesToPrompt as c, CursorRunner as i, normalizeModel as l, engines as n, toCodexModelCatalog as o, version as r, toOpenAIModelList as s, startServer as t, responsesToMessages as u };
|
|
748
|
-
|
|
749
|
-
//# sourceMappingURL=server-Bk7ol2lA.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cursor-agent-bridge",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Responses-compatible API bridge for Cursor Agent CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"homepage": "https://github.com/xwartz/cursor-agent-bridge#readme",
|
|
14
14
|
"bin": {
|
|
15
|
-
"cursor-agent-bridge": "./dist/cli.mjs"
|
|
15
|
+
"cursor-agent-bridge": "./dist/cli.mjs",
|
|
16
|
+
"cab": "./dist/cli.mjs"
|
|
16
17
|
},
|
|
17
18
|
"exports": {
|
|
18
19
|
".": {
|
package/dist/cli.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":["execFileAsync","packageJson.version","packageJson.version"],"sources":["../src/cli-args.ts","../src/codex-config.ts","../src/doctor.ts","../src/launch-agent.ts","../src/upgrade.ts","../src/cli.ts"],"sourcesContent":["export function readArg(name: string, fallback: string | undefined) {\n const index = process.argv.indexOf(name)\n if (index < 0) return fallback\n const value = process.argv[index + 1]\n if (!value || value.startsWith(\"-\"))\n throw new Error(`Missing value for ${name}`)\n return value\n}\n\nexport function parsePort(value: string | undefined, fallback: number) {\n if (value === undefined) return fallback\n const port = Number(value)\n if (!Number.isInteger(port) || port < 1 || port > 65_535) {\n throw new Error(`Invalid port: ${value}`)\n }\n return port\n}\n\nexport function readHostAndPort(defaultHost = \"127.0.0.1\", defaultPort = 4646) {\n const host = readArg(\"--host\", process.env.HOST) ?? defaultHost\n const port = parsePort(readArg(\"--port\", process.env.PORT), defaultPort)\n return { host, port }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { dirname, join } from \"node:path\"\n\nexport const DEFAULT_CODEX_PROFILE = \"cursor\"\n\nexport type CodexConfigOptions = {\n host: string\n port: number\n profile?: string\n}\n\nexport type CodexConfigFields = {\n modelProvider?: string\n model?: string\n providerName?: string\n baseUrl?: string\n wireApi?: string\n}\n\nexport type CodexConfigCheckResult = {\n ok: boolean\n issues: string[]\n}\n\nexport type WriteCodexConfigResult = {\n path: string\n created: boolean\n updated: boolean\n}\n\nexport function resolveCodexConfigPath(\n profile = DEFAULT_CODEX_PROFILE,\n homeDir = homedir(),\n) {\n assertValidProfile(profile)\n return join(homeDir, \".codex\", `${profile}.config.toml`)\n}\n\nexport function buildBaseUrl(host: string, port: number) {\n return `http://${host}:${port}/v1`\n}\n\nexport function buildCodexConfigToml(options: CodexConfigOptions) {\n const profile = options.profile ?? DEFAULT_CODEX_PROFILE\n assertValidProfile(profile)\n const baseUrl = buildBaseUrl(options.host, options.port)\n return `model_provider = ${formatTomlString(profile)}\nmodel = \"auto\"\n\n[model_providers.${profile}]\nname = \"Cursor Agent Bridge\"\nbase_url = ${formatTomlString(baseUrl)}\nwire_api = \"responses\"\n`\n}\n\nexport function parseCodexConfig(\n content: string,\n profile = DEFAULT_CODEX_PROFILE,\n) {\n assertValidProfile(profile)\n const fields: CodexConfigFields = {}\n const providerSection = `model_providers.${profile}`\n let section = \"\"\n\n for (const rawLine of content.split(\"\\n\")) {\n const line = rawLine.trim()\n if (!line || line.startsWith(\"#\")) continue\n\n const sectionMatch = line.match(/^\\[(.+)\\]$/)\n if (sectionMatch) {\n section = sectionMatch[1] ?? \"\"\n continue\n }\n\n const assignment = line.match(/^([A-Za-z0-9_.-]+)\\s*=\\s*(.+)$/)\n if (!assignment) continue\n\n const key = assignment[1] ?? \"\"\n const value = parseTomlValue(assignment[2] ?? \"\")\n\n if (section === providerSection) {\n if (key === \"name\") fields.providerName = value\n if (key === \"base_url\") fields.baseUrl = value\n if (key === \"wire_api\") fields.wireApi = value\n continue\n }\n\n if (section) continue\n if (key === \"model_provider\") fields.modelProvider = value\n if (key === \"model\") fields.model = value\n }\n\n return fields\n}\n\nexport function checkCodexConfig(\n content: string,\n options: CodexConfigOptions,\n): CodexConfigCheckResult {\n const profile = options.profile ?? DEFAULT_CODEX_PROFILE\n const expectedBaseUrl = buildBaseUrl(options.host, options.port)\n const fields = parseCodexConfig(content, profile)\n const issues: string[] = []\n\n if (fields.modelProvider !== profile) {\n issues.push(\n `model_provider should be \"${profile}\"${\n fields.modelProvider\n ? `, found \"${fields.modelProvider}\"`\n : \", but it is missing\"\n }`,\n )\n }\n\n if (fields.baseUrl !== expectedBaseUrl) {\n issues.push(\n `base_url should be \"${expectedBaseUrl}\"${\n fields.baseUrl ? `, found \"${fields.baseUrl}\"` : \", but it is missing\"\n }`,\n )\n }\n\n if (fields.wireApi !== \"responses\") {\n issues.push(\n `wire_api should be \"responses\"${\n fields.wireApi ? `, found \"${fields.wireApi}\"` : \", but it is missing\"\n }`,\n )\n }\n\n return { ok: issues.length === 0, issues }\n}\n\nexport async function writeCodexConfig(\n options: CodexConfigOptions & {\n filePath: string\n force?: boolean\n },\n): Promise<WriteCodexConfigResult> {\n let existing: string | undefined\n\n try {\n existing = await readFile(options.filePath, \"utf8\")\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error\n }\n\n if (existing === undefined) {\n await mkdir(dirname(options.filePath), { recursive: true })\n await writeFile(options.filePath, buildCodexConfigToml(options), \"utf8\")\n return { path: options.filePath, created: true, updated: false }\n }\n\n const merged = mergeCodexConfig(existing, options)\n if (\"error\" in merged) throw new Error(merged.error)\n\n if (!merged.changed) {\n return { path: options.filePath, created: false, updated: false }\n }\n\n await writeFile(options.filePath, merged.content, \"utf8\")\n return { path: options.filePath, created: false, updated: true }\n}\n\nfunction mergeCodexConfig(\n existing: string,\n options: CodexConfigOptions & { force?: boolean },\n) {\n const profile = options.profile ?? DEFAULT_CODEX_PROFILE\n assertValidProfile(profile)\n const providerSection = `model_providers.${profile}`\n const expected = buildCodexConfigToml(options)\n const parsed = parseCodexConfig(existing, profile)\n\n if (\n parsed.modelProvider &&\n parsed.modelProvider !== profile &&\n !options.force\n ) {\n return {\n error: `model_provider is \"${parsed.modelProvider}\". Re-run with --force to switch it to \"${profile}\".`,\n }\n }\n\n const lines = existing.split(\"\\n\")\n const output: string[] = []\n let section = \"\"\n let inProviderSection = false\n let sawModelProvider = false\n let sawModel = false\n let sawProviderSection = false\n const handledProviderKeys = new Set<string>()\n\n for (const rawLine of lines) {\n const trimmed = rawLine.trim()\n const sectionMatch = trimmed.match(/^\\[(.+)\\]$/)\n if (sectionMatch) {\n if (inProviderSection) appendMissingProviderKeys()\n section = sectionMatch[1] ?? \"\"\n inProviderSection = section === providerSection\n if (inProviderSection) sawProviderSection = true\n output.push(rawLine)\n continue\n }\n\n const assignment = trimmed.match(/^([A-Za-z0-9_.-]+)\\s*=\\s*(.+)$/)\n if (!assignment) {\n output.push(rawLine)\n continue\n }\n\n const key = assignment[1] ?? \"\"\n\n if (!section) {\n if (key === \"model_provider\") {\n sawModelProvider = true\n output.push(`model_provider = ${formatTomlString(profile)}`)\n continue\n }\n if (key === \"model\") {\n sawModel = true\n if (parsed.model === undefined || options.force) {\n output.push('model = \"auto\"')\n } else {\n output.push(rawLine)\n }\n continue\n }\n }\n\n if (inProviderSection) {\n if (key === \"name\") {\n handledProviderKeys.add(\"name\")\n output.push('name = \"Cursor Agent Bridge\"')\n continue\n }\n if (key === \"base_url\") {\n handledProviderKeys.add(\"base_url\")\n output.push(\n `base_url = ${formatTomlString(buildBaseUrl(options.host, options.port))}`,\n )\n continue\n }\n if (key === \"wire_api\") {\n handledProviderKeys.add(\"wire_api\")\n output.push('wire_api = \"responses\"')\n continue\n }\n }\n\n output.push(rawLine)\n }\n\n if (inProviderSection) appendMissingProviderKeys()\n\n const missingTopLevel: string[] = []\n if (!sawModelProvider)\n missingTopLevel.push(`model_provider = ${formatTomlString(profile)}`)\n if (!sawModel) missingTopLevel.push('model = \"auto\"')\n\n let content = output.join(\"\\n\").trimEnd()\n if (missingTopLevel.length > 0) {\n content = `${missingTopLevel.join(\"\\n\")}\\n${content}`\n }\n\n if (!sawProviderSection) {\n const providerBlock = expected.split(\"\\n\").slice(3).join(\"\\n\")\n content = `${content}\\n\\n${providerBlock}\\n`\n }\n\n const changed = normalizeToml(content) !== normalizeToml(existing)\n return { content: `${content.trimEnd()}\\n`, changed }\n\n function appendMissingProviderKeys() {\n if (!handledProviderKeys.has(\"name\")) {\n output.push('name = \"Cursor Agent Bridge\"')\n }\n if (!handledProviderKeys.has(\"base_url\")) {\n output.push(\n `base_url = ${formatTomlString(buildBaseUrl(options.host, options.port))}`,\n )\n }\n if (!handledProviderKeys.has(\"wire_api\")) {\n output.push('wire_api = \"responses\"')\n }\n }\n}\n\nfunction assertValidProfile(profile: string) {\n if (/^[A-Za-z0-9_-]+$/.test(profile)) return\n throw new Error(\n \"Invalid Codex profile. Use only letters, numbers, underscores, or hyphens.\",\n )\n}\n\nfunction formatTomlString(value: string) {\n return `\"${value\n .replaceAll(\"\\\\\", \"\\\\\\\\\")\n .replaceAll('\"', '\\\\\"')\n .replaceAll(\"\\b\", \"\\\\b\")\n .replaceAll(\"\\t\", \"\\\\t\")\n .replaceAll(\"\\n\", \"\\\\n\")\n .replaceAll(\"\\f\", \"\\\\f\")\n .replaceAll(\"\\r\", \"\\\\r\")}\"`\n}\n\nfunction normalizeToml(content: string) {\n return content.replace(/\\r\\n/g, \"\\n\").trimEnd()\n}\n\nfunction parseTomlValue(raw: string) {\n const trimmed = stripInlineTomlComment(raw).trim()\n if (trimmed.startsWith('\"') && trimmed.endsWith('\"')) {\n return unescapeTomlString(trimmed.slice(1, -1))\n }\n if (trimmed.startsWith(\"'\") && trimmed.endsWith(\"'\")) {\n return trimmed.slice(1, -1)\n }\n return trimmed\n}\n\nfunction unescapeTomlString(value: string) {\n return value.replace(\n /\\\\([\"\\\\btnfr])/g,\n (_match, escaped: string) =>\n ({\n '\"': '\"',\n \"\\\\\": \"\\\\\",\n b: \"\\b\",\n t: \"\\t\",\n n: \"\\n\",\n f: \"\\f\",\n r: \"\\r\",\n })[escaped] ?? escaped,\n )\n}\n\nfunction stripInlineTomlComment(raw: string) {\n let quote: string | undefined\n for (let index = 0; index < raw.length; index += 1) {\n const char = raw[index]\n if ((char === '\"' || char === \"'\") && raw[index - 1] !== \"\\\\\") {\n quote = quote === char ? undefined : (quote ?? char)\n continue\n }\n\n if (!quote && char === \"#\") {\n return raw.slice(0, index)\n }\n }\n\n return raw\n}\n","import { execFile } from \"node:child_process\"\nimport { readFile } from \"node:fs/promises\"\nimport { promisify } from \"node:util\"\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport {\n checkCodexConfig,\n DEFAULT_CODEX_PROFILE,\n resolveCodexConfigPath,\n} from \"./codex-config.js\"\nimport { CursorRunner } from \"./cursor/runner.js\"\n\nconst execFileAsync = promisify(execFile)\n\nexport type DoctorCheck = {\n name: string\n ok: boolean\n message: string\n hint?: string\n}\n\nexport type ExecFileFn = (\n file: string,\n args?: readonly string[] | null,\n options?: { timeout?: number },\n) => Promise<unknown>\n\nexport type DoctorOptions = {\n host: string\n port: number\n agentPath?: string\n profile?: string\n nodeVersionRange?: string\n codexConfigPath?: string\n skipCodexConfig?: boolean\n runner?: CursorRunner\n fetchFn?: typeof fetch\n execFileFn?: ExecFileFn\n readFileFn?: typeof readFile\n}\n\nexport async function runDoctor(options: DoctorOptions) {\n const checks: DoctorCheck[] = []\n const fetchFn = options.fetchFn ?? fetch\n const execFileFn = options.execFileFn ?? execFileAsync\n const readFileFn = options.readFileFn ?? readFile\n const agentPath =\n options.agentPath ?? process.env.CURSOR_AGENT_PATH ?? \"agent\"\n const profile = options.profile ?? DEFAULT_CODEX_PROFILE\n const codexConfigPath =\n options.codexConfigPath ?? resolveCodexConfigPath(profile)\n\n checks.push(\n checkNodeVersion(options.nodeVersionRange ?? packageJson.engines.node),\n )\n checks.push({\n name: \"bridge-version\",\n ok: true,\n message: `cursor-agent-bridge ${packageJson.version}`,\n })\n\n const agentCheck = await checkAgentExecutable(agentPath, execFileFn)\n checks.push(agentCheck)\n\n if (agentCheck.ok) {\n checks.push(await checkAgentLogin(agentPath, options.runner))\n }\n\n checks.push(await checkBridgeHealth(options.host, options.port, fetchFn))\n\n if (!options.skipCodexConfig) {\n checks.push(\n await checkCodexConfigFile({\n codexConfigPath,\n host: options.host,\n port: options.port,\n profile,\n readFileFn,\n }),\n )\n }\n\n return {\n ok: checks.every((check) => check.ok),\n checks,\n }\n}\n\nexport function formatDoctorReport(result: {\n ok: boolean\n checks: DoctorCheck[]\n}) {\n const lines = result.checks.map((check) => {\n const prefix = check.ok ? \"✓\" : \"✗\"\n const hint = check.hint ? `\\n → ${check.hint}` : \"\"\n return `${prefix} ${check.name}: ${check.message}${hint}`\n })\n\n lines.push(\"\")\n lines.push(\n result.ok\n ? \"All checks passed. Codex can use Cursor Agent through the bridge.\"\n : \"Some checks failed. Fix the items above before starting Codex.\",\n )\n\n return `${lines.join(\"\\n\")}\\n`\n}\n\nfunction checkNodeVersion(requiredRange: string): DoctorCheck {\n const current = process.version.slice(1)\n const minimum = parseMinimumNodeVersion(requiredRange)\n const ok = compareNodeVersion(current, minimum) >= 0\n\n return ok\n ? {\n name: \"node-version\",\n ok,\n message: `Node ${current} satisfies ${requiredRange}`,\n }\n : {\n name: \"node-version\",\n ok,\n message: `Node ${current} does not satisfy ${requiredRange}`,\n hint: `Install Node ${minimum} or newer.`,\n }\n}\n\nasync function checkAgentExecutable(\n agentPath: string,\n execFileFn: ExecFileFn,\n): Promise<DoctorCheck> {\n try {\n await execFileFn(agentPath, [\"--help\"], { timeout: 5_000 })\n return {\n name: \"agent-cli\",\n ok: true,\n message: `Cursor Agent CLI found at ${agentPath}`,\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Cursor Agent CLI not found\"\n return {\n name: \"agent-cli\",\n ok: false,\n message,\n hint: \"Install the Cursor Agent CLI and ensure `agent` is on PATH, or set CURSOR_AGENT_PATH.\",\n }\n }\n}\n\nasync function checkAgentLogin(\n agentPath: string,\n runner = new CursorRunner({ agentPath }),\n): Promise<DoctorCheck> {\n try {\n const models = await runner.listModels({\n refresh: true,\n })\n if (models.length === 0) {\n return {\n name: \"agent-login\",\n ok: false,\n message: \"Cursor Agent responded, but returned no models\",\n hint: \"Run `agent login` and confirm `agent --list-models` returns models.\",\n }\n }\n\n return {\n name: \"agent-login\",\n ok: true,\n message: `Cursor Agent is logged in (${models.length} models available)`,\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Cursor Agent login check failed\"\n return {\n name: \"agent-login\",\n ok: false,\n message,\n hint: \"Run `agent login` and retry `cursor-agent-bridge doctor`.\",\n }\n }\n}\n\nasync function checkBridgeHealth(\n host: string,\n port: number,\n fetchFn: typeof fetch,\n): Promise<DoctorCheck> {\n const url = `http://${host}:${port}/health`\n try {\n const response = await fetchFn(url, { signal: AbortSignal.timeout(3_000) })\n if (!response.ok) {\n return {\n name: \"bridge-health\",\n ok: false,\n message: `${url} returned HTTP ${response.status}`,\n hint: \"Start the bridge with `cursor-agent-bridge serve` or `cursor-agent-bridge launch-agent install`.\",\n }\n }\n\n const payload = (await response.json()) as { version?: string }\n return {\n name: \"bridge-health\",\n ok: true,\n message: payload.version\n ? `Bridge is listening on ${url} (version ${payload.version})`\n : `Bridge is listening on ${url}`,\n }\n } catch (error) {\n const message =\n error instanceof Error ? error.message : \"Bridge health check failed\"\n return {\n name: \"bridge-health\",\n ok: false,\n message,\n hint: \"Start the bridge with `cursor-agent-bridge serve` or `cursor-agent-bridge launch-agent install`.\",\n }\n }\n}\n\nasync function checkCodexConfigFile(options: {\n codexConfigPath: string\n host: string\n port: number\n profile: string\n readFileFn: typeof readFile\n}): Promise<DoctorCheck> {\n try {\n const content = await options.readFileFn(options.codexConfigPath, \"utf8\")\n const result = checkCodexConfig(content, {\n host: options.host,\n port: options.port,\n profile: options.profile,\n })\n\n if (result.ok) {\n return {\n name: \"codex-config\",\n ok: true,\n message: `Codex config looks correct at ${options.codexConfigPath}`,\n }\n }\n\n return {\n name: \"codex-config\",\n ok: false,\n message: result.issues.join(\"; \"),\n hint: \"Run `cursor-agent-bridge config write` or `cursor-agent-bridge config print`.\",\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return {\n name: \"codex-config\",\n ok: false,\n message: `Codex config not found at ${options.codexConfigPath}`,\n hint: \"Run `cursor-agent-bridge config write` to create it.\",\n }\n }\n\n const message =\n error instanceof Error ? error.message : \"Codex config check failed\"\n return {\n name: \"codex-config\",\n ok: false,\n message,\n hint: \"Verify the Codex config path and file permissions.\",\n }\n }\n}\n\nfunction parseMinimumNodeVersion(range: string) {\n const match = range.match(/(\\d+)\\.(\\d+)(?:\\.(\\d+))?/)\n if (!match) return \"0.0.0\"\n return `${match[1]}.${match[2]}.${match[3] ?? 0}`\n}\n\nfunction compareNodeVersion(left: string, right: string) {\n const toParts = (value: string) =>\n value.split(\".\").map((part) => Number.parseInt(part, 10) || 0)\n const [leftMajor = 0, leftMinor = 0, leftPatch = 0] = toParts(left)\n const [rightMajor = 0, rightMinor = 0, rightPatch = 0] = toParts(right)\n\n if (leftMajor !== rightMajor) return leftMajor - rightMajor\n if (leftMinor !== rightMinor) return leftMinor - rightMinor\n return leftPatch - rightPatch\n}\n","import { execFileSync } from \"node:child_process\"\nimport {\n chmodSync,\n existsSync,\n mkdirSync,\n rmSync,\n writeFileSync,\n} from \"node:fs\"\nimport { homedir } from \"node:os\"\nimport { dirname, join, resolve } from \"node:path\"\n\nconst defaultLabel = \"com.xwartz.cursor-agent-bridge\"\nconst defaultLogDir = join(homedir(), \".codex\", \"logs\")\n\nexport type LaunchAgentOptions = {\n cliPath: string\n host?: string\n port?: number\n agentPath?: string\n label?: string\n}\n\nexport type LaunchAgentPaths = {\n label: string\n plistPath: string\n stdoutPath: string\n stderrPath: string\n}\n\nexport function getLaunchAgentPaths(label = defaultLabel): LaunchAgentPaths {\n return {\n label,\n plistPath: join(homedir(), \"Library\", \"LaunchAgents\", `${label}.plist`),\n stdoutPath: join(defaultLogDir, \"cursor-agent-bridge.log\"),\n stderrPath: join(defaultLogDir, \"cursor-agent-bridge.err.log\"),\n }\n}\n\nexport function createLaunchAgentPlist(options: LaunchAgentOptions) {\n const label = options.label ?? defaultLabel\n const host = options.host ?? \"127.0.0.1\"\n const port = options.port ?? 4646\n const paths = getLaunchAgentPaths(label)\n const args = [\n resolve(options.cliPath),\n \"serve\",\n \"--host\",\n host,\n \"--port\",\n String(port),\n ]\n const env: Record<string, string> = {\n PATH: [\n dirname(resolve(options.cliPath)),\n join(homedir(), \".local\", \"bin\"),\n \"/usr/local/bin\",\n \"/opt/homebrew/bin\",\n \"/usr/bin\",\n \"/bin\",\n \"/usr/sbin\",\n \"/sbin\",\n ].join(\":\"),\n }\n\n if (options.agentPath) {\n env.CURSOR_AGENT_PATH = options.agentPath\n }\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${escapePlist(label)}</string>\n\n <key>ProgramArguments</key>\n <array>\n${args.map((arg) => ` <string>${escapePlist(arg)}</string>`).join(\"\\n\")}\n </array>\n\n <key>EnvironmentVariables</key>\n <dict>\n${Object.entries(env)\n .map(\n ([key, value]) =>\n ` <key>${escapePlist(key)}</key>\\n <string>${escapePlist(value)}</string>`,\n )\n .join(\"\\n\")}\n </dict>\n\n <key>RunAtLoad</key>\n <true/>\n\n <key>KeepAlive</key>\n <true/>\n\n <key>StandardOutPath</key>\n <string>${escapePlist(paths.stdoutPath)}</string>\n\n <key>StandardErrorPath</key>\n <string>${escapePlist(paths.stderrPath)}</string>\n</dict>\n</plist>\n`\n}\n\nexport function installLaunchAgent(options: LaunchAgentOptions) {\n ensureMacOS()\n const label = options.label ?? defaultLabel\n const paths = getLaunchAgentPaths(label)\n mkdirSync(dirname(paths.plistPath), { recursive: true })\n mkdirSync(defaultLogDir, { recursive: true })\n\n if (existsSync(paths.plistPath)) {\n bootout(paths.plistPath)\n }\n\n writeFileSync(paths.plistPath, createLaunchAgentPlist(options))\n chmodSync(paths.plistPath, 0o644)\n execFileSync(\"launchctl\", [\"bootstrap\", launchctlDomain(), paths.plistPath], {\n stdio: \"pipe\",\n })\n return paths\n}\n\nexport function uninstallLaunchAgent(label = defaultLabel) {\n ensureMacOS()\n const paths = getLaunchAgentPaths(label)\n bootout(paths.plistPath)\n rmSync(paths.plistPath, { force: true })\n return paths\n}\n\nexport function printLaunchAgentStatus(label = defaultLabel) {\n ensureMacOS()\n return execFileSync(\"launchctl\", [\"print\", `${launchctlDomain()}/${label}`], {\n encoding: \"utf8\",\n })\n}\n\nfunction bootout(plistPath: string) {\n try {\n execFileSync(\"launchctl\", [\"bootout\", launchctlDomain(), plistPath], {\n stdio: \"pipe\",\n })\n } catch {\n // It is fine if the service is not loaded yet.\n }\n}\n\nfunction launchctlDomain() {\n return `gui/${process.getuid?.() ?? execFileSync(\"id\", [\"-u\"], { encoding: \"utf8\" }).trim()}`\n}\n\nfunction ensureMacOS() {\n if (process.platform !== \"darwin\") {\n throw new Error(\"LaunchAgent management is only available on macOS.\")\n }\n}\n\nfunction escapePlist(value: string) {\n return value\n .replaceAll(\"&\", \"&\")\n .replaceAll(\"<\", \"<\")\n .replaceAll(\">\", \">\")\n .replaceAll('\"', \""\")\n .replaceAll(\"'\", \"'\")\n}\n","import { execFile, spawn } from \"node:child_process\"\nimport { existsSync } from \"node:fs\"\nimport { promisify } from \"node:util\"\nimport { getLaunchAgentPaths } from \"./launch-agent.js\"\n\nconst execFileAsync = promisify(execFile)\n\nexport const PACKAGE_NAME = \"cursor-agent-bridge\"\nexport const DEFAULT_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`\nconst REGISTRY_TIMEOUT_MS = 10_000\n\nexport type PackageManager = \"npm\" | \"pnpm\"\nexport type PackageManagerPreference = PackageManager | \"auto\"\n\nexport type ExecFileFn = (\n file: string,\n args?: readonly string[] | null,\n options?: { env?: NodeJS.ProcessEnv },\n) => Promise<unknown>\n\nexport type SpawnFn = (\n command: string,\n args: readonly string[],\n options: { stdio: \"inherit\"; env?: NodeJS.ProcessEnv },\n) => {\n on(event: \"error\", listener: (error: Error) => void): unknown\n on(event: \"close\", listener: (code: number | null) => void): unknown\n}\n\nexport type UpgradeOptions = {\n currentVersion: string\n checkOnly?: boolean\n target?: string\n manager?: PackageManagerPreference\n registryUrl?: string\n fetchFn?: typeof fetch\n spawnFn?: SpawnFn\n execFileFn?: ExecFileFn\n existsFn?: typeof existsSync\n log?: (...args: unknown[]) => void\n errorLog?: (...args: unknown[]) => void\n}\n\nexport function compareSemver(left: string, right: string): -1 | 0 | 1 {\n const toParts = (value: string) => {\n const [major = 0, minor = 0, patch = 0] = value\n .split(\".\")\n .map((part) => Number.parseInt(part, 10) || 0)\n return [major, minor, patch] as const\n }\n const [leftMajor, leftMinor, leftPatch] = toParts(left)\n const [rightMajor, rightMinor, rightPatch] = toParts(right)\n\n if (leftMajor !== rightMajor) {\n return leftMajor < rightMajor ? -1 : 1\n }\n if (leftMinor !== rightMinor) {\n return leftMinor < rightMinor ? -1 : 1\n }\n if (leftPatch !== rightPatch) {\n return leftPatch < rightPatch ? -1 : 1\n }\n return 0\n}\n\nexport async function fetchLatestVersion(options?: {\n registryUrl?: string\n fetchFn?: typeof fetch\n timeoutMs?: number\n}): Promise<string> {\n const registryUrl = options?.registryUrl ?? DEFAULT_REGISTRY_URL\n const fetchFn = options?.fetchFn ?? fetch\n const timeoutMs = options?.timeoutMs ?? REGISTRY_TIMEOUT_MS\n const controller = new AbortController()\n const timeout = setTimeout(() => controller.abort(), timeoutMs)\n\n try {\n const response = await fetchFn(registryUrl, { signal: controller.signal })\n if (!response.ok) {\n throw new Error(`Registry returned ${response.status}`)\n }\n\n const payload = (await response.json()) as { version?: string }\n if (!payload.version) {\n throw new Error(\"Registry response missing version\")\n }\n return payload.version\n } finally {\n clearTimeout(timeout)\n }\n}\n\nasync function commandExists(\n command: string,\n execFileFn: ExecFileFn,\n): Promise<boolean> {\n try {\n await execFileFn(\"which\", [command])\n return true\n } catch {\n return false\n }\n}\n\nexport async function detectPackageManager(\n preference: PackageManagerPreference,\n execFileFn: ExecFileFn = execFileAsync,\n): Promise<PackageManager> {\n if (preference === \"npm\") return \"npm\"\n if (preference === \"pnpm\") return \"pnpm\"\n\n if (!(await commandExists(\"pnpm\", execFileFn))) {\n return \"npm\"\n }\n\n try {\n await execFileFn(\"pnpm\", [\"list\", \"-g\", PACKAGE_NAME, \"--json\"], {\n env: process.env,\n })\n return \"pnpm\"\n } catch {\n return \"npm\"\n }\n}\n\nexport function buildInstallCommand(\n manager: PackageManager,\n target: string,\n): { command: string; args: string[] } {\n const versionSpec =\n target === \"latest\" ? \"@latest\" : `@${target.replace(/^@/, \"\")}`\n const packageSpec = `${PACKAGE_NAME}${versionSpec}`\n\n if (manager === \"pnpm\") {\n return { command: \"pnpm\", args: [\"add\", \"-g\", packageSpec] }\n }\n\n return { command: \"npm\", args: [\"install\", \"-g\", packageSpec] }\n}\n\nfunction printManualUpgradeHint(errorLog: (...args: unknown[]) => void) {\n errorLog(\"Upgrade manually:\")\n errorLog(` pnpm add -g ${PACKAGE_NAME}@latest`)\n errorLog(` npm install -g ${PACKAGE_NAME}@latest`)\n}\n\nasync function resolveTargetVersion(\n target: string,\n registryUrl: string,\n fetchFn: typeof fetch,\n): Promise<string> {\n if (target === \"latest\") {\n return fetchLatestVersion({ registryUrl, fetchFn })\n }\n return target.replace(/^@/, \"\")\n}\n\nasync function runInstall(\n manager: PackageManager,\n target: string,\n spawnFn: SpawnFn,\n): Promise<number> {\n const { command, args } = buildInstallCommand(manager, target)\n return new Promise((resolve, reject) => {\n const child = spawnFn(command, args, {\n stdio: \"inherit\",\n env: process.env,\n })\n\n child.on(\"error\", reject)\n child.on(\"close\", (code) => resolve(code ?? 1))\n })\n}\n\nexport async function runUpgrade(options: UpgradeOptions): Promise<number> {\n const log = options.log ?? console.log\n const errorLog = options.errorLog ?? console.error\n const checkOnly = options.checkOnly ?? false\n const target = options.target ?? \"latest\"\n const managerPreference = options.manager ?? \"auto\"\n const registryUrl = options.registryUrl ?? DEFAULT_REGISTRY_URL\n const fetchFn = options.fetchFn ?? fetch\n const spawnFn: SpawnFn =\n options.spawnFn ??\n ((command, args, spawnOptions) => spawn(command, args, spawnOptions))\n const execFileFn = options.execFileFn ?? execFileAsync\n const existsFn = options.existsFn ?? existsSync\n\n let targetVersion: string\n try {\n targetVersion = await resolveTargetVersion(target, registryUrl, fetchFn)\n } catch (error) {\n errorLog(\n `Failed to check for updates: ${error instanceof Error ? error.message : String(error)}`,\n )\n printManualUpgradeHint(errorLog)\n return 1\n }\n\n const comparison = compareSemver(options.currentVersion, targetVersion)\n if (comparison >= 0) {\n log(`${PACKAGE_NAME} is up to date (${options.currentVersion})`)\n return 0\n }\n\n if (checkOnly) {\n log(`Update available: ${options.currentVersion} -> ${targetVersion}`)\n return 1\n }\n\n let manager: PackageManager\n manager = await detectPackageManager(managerPreference, execFileFn)\n\n log(`Installing ${PACKAGE_NAME}@${targetVersion} via ${manager}...`)\n try {\n const exitCode = await runInstall(manager, target, spawnFn)\n if (exitCode !== 0) {\n errorLog(`${manager} install failed with exit code ${exitCode}`)\n printManualUpgradeHint(errorLog)\n return exitCode\n }\n } catch (error) {\n errorLog(\n `Install failed: ${error instanceof Error ? error.message : String(error)}`,\n )\n printManualUpgradeHint(errorLog)\n return 1\n }\n\n log(`Installed ${PACKAGE_NAME}@${targetVersion}`)\n log(\"Run `cursor-agent-bridge --version` to verify the upgrade.\")\n\n const launchAgentPlist = getLaunchAgentPaths().plistPath\n if (existsFn(launchAgentPlist)) {\n log(\n \"LaunchAgent detected. Run `cursor-agent-bridge launch-agent install` to refresh the service.\",\n )\n }\n\n return 0\n}\n","#!/usr/bin/env node\n\nimport { readFile } from \"node:fs/promises\"\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport { toOpenAIModelList } from \"./adapter/models.js\"\nimport { readArg, readHostAndPort } from \"./cli-args.js\"\nimport {\n buildCodexConfigToml,\n checkCodexConfig,\n DEFAULT_CODEX_PROFILE,\n resolveCodexConfigPath,\n writeCodexConfig,\n} from \"./codex-config.js\"\nimport { CursorRunner } from \"./cursor/runner.js\"\nimport { formatDoctorReport, runDoctor } from \"./doctor.js\"\nimport {\n installLaunchAgent,\n printLaunchAgentStatus,\n uninstallLaunchAgent,\n} from \"./launch-agent.js\"\nimport { startServer } from \"./server.js\"\nimport { runUpgrade } from \"./upgrade.js\"\n\nconst command =\n process.argv[2] && !process.argv[2]?.startsWith(\"-\")\n ? process.argv[2]\n : \"serve\"\n\nif (\n command === \"help\" ||\n process.argv.includes(\"--help\") ||\n process.argv.includes(\"-h\")\n) {\n console.log(`cursor-agent-bridge\n\nUsage:\n cursor-agent-bridge serve [--host 127.0.0.1] [--port 4646]\n cursor-agent-bridge doctor [--host 127.0.0.1] [--port 4646] [--profile cursor] [--file ~/.codex/cursor.config.toml] [--skip-codex-config]\n cursor-agent-bridge config print [--host 127.0.0.1] [--port 4646] [--profile cursor]\n cursor-agent-bridge config check [--file ~/.codex/cursor.config.toml] [--host 127.0.0.1] [--port 4646] [--profile cursor]\n cursor-agent-bridge config write [--file ~/.codex/cursor.config.toml] [--host 127.0.0.1] [--port 4646] [--profile cursor] [--force]\n cursor-agent-bridge models [--json] [--refresh]\n cursor-agent-bridge launch-agent install [--host 127.0.0.1] [--port 4646] [--agent-path agent]\n cursor-agent-bridge launch-agent uninstall\n cursor-agent-bridge launch-agent status\n cursor-agent-bridge upgrade [--check] [--target latest] [--manager auto|npm|pnpm]\n\nEnvironment:\n HOST Listen host, default 127.0.0.1\n PORT Listen port, default 4646\n CURSOR_AGENT_PATH Cursor Agent CLI path, default agent\n`)\n process.exit(0)\n}\n\nif (command === \"version\" || process.argv.includes(\"--version\")) {\n console.log(packageJson.version)\n process.exit(0)\n}\n\nif (command === \"upgrade\") {\n const checkOnly = process.argv.includes(\"--check\")\n const target = readArg(\"--target\", \"latest\") ?? \"latest\"\n const manager = readArg(\"--manager\", \"auto\") ?? \"auto\"\n\n if (manager !== \"auto\" && manager !== \"npm\" && manager !== \"pnpm\") {\n console.error(\"Invalid --manager value. Use auto, npm, or pnpm.\")\n process.exit(1)\n }\n\n const exitCode = await runUpgrade({\n currentVersion: packageJson.version,\n checkOnly,\n target,\n manager,\n })\n process.exit(exitCode)\n}\n\nif (command === \"doctor\") {\n try {\n const { host, port } = readHostAndPort()\n const profile =\n readArg(\"--profile\", DEFAULT_CODEX_PROFILE) ?? DEFAULT_CODEX_PROFILE\n const codexConfigPath = readArg(\"--file\", undefined)\n const result = await runDoctor({\n host,\n port,\n profile,\n skipCodexConfig: process.argv.includes(\"--skip-codex-config\"),\n ...(process.env.CURSOR_AGENT_PATH\n ? { agentPath: process.env.CURSOR_AGENT_PATH }\n : {}),\n ...(codexConfigPath ? { codexConfigPath } : {}),\n })\n process.stdout.write(formatDoctorReport(result))\n process.exit(result.ok ? 0 : 1)\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n}\n\nif (command === \"config\") {\n const action = process.argv[3] ?? \"print\"\n try {\n const { host, port } = readHostAndPort()\n const profile =\n readArg(\"--profile\", DEFAULT_CODEX_PROFILE) ?? DEFAULT_CODEX_PROFILE\n const filePath =\n readArg(\"--file\", undefined) ?? resolveCodexConfigPath(profile)\n\n if (action === \"print\") {\n process.stdout.write(buildCodexConfigToml({ host, port, profile }))\n console.error(`Start Codex with: codex --profile ${profile}`)\n process.exit(0)\n }\n\n if (action === \"check\") {\n const content = await readFile(filePath, \"utf8\")\n const result = checkCodexConfig(content, { host, port, profile })\n if (result.ok) {\n console.log(`Codex config looks correct: ${filePath}`)\n process.exit(0)\n }\n\n for (const issue of result.issues) {\n console.error(issue)\n }\n process.exit(1)\n }\n\n if (action === \"write\") {\n const result = await writeCodexConfig({\n filePath,\n host,\n port,\n profile,\n force: process.argv.includes(\"--force\"),\n })\n\n if (result.created) {\n console.log(`Created Codex config at ${result.path}`)\n } else if (result.updated) {\n console.log(`Updated Codex config at ${result.path}`)\n } else {\n console.log(`Codex config already up to date at ${result.path}`)\n }\n\n console.log(`Start Codex with: codex --profile ${profile}`)\n process.exit(0)\n }\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n\n console.error(`Unknown config action: ${action}`)\n process.exit(1)\n}\n\nif (command === \"models\") {\n try {\n const runner = new CursorRunner({\n ...(process.env.CURSOR_AGENT_PATH\n ? { agentPath: process.env.CURSOR_AGENT_PATH }\n : {}),\n })\n const models = await runner.listModels({\n refresh: process.argv.includes(\"--refresh\"),\n })\n\n if (process.argv.includes(\"--json\")) {\n console.log(JSON.stringify(toOpenAIModelList(models), null, 2))\n process.exit(0)\n }\n\n for (const model of models) {\n console.log(model.id)\n }\n process.exit(0)\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n}\n\nif (command === \"launch-agent\") {\n const action = process.argv[3] ?? \"status\"\n try {\n if (action === \"install\") {\n const { host, port } = readHostAndPort()\n const agentPath = readArg(\"--agent-path\", process.env.CURSOR_AGENT_PATH)\n const paths = installLaunchAgent({\n cliPath: process.argv[1] ?? \"cursor-agent-bridge\",\n host,\n port,\n ...(agentPath ? { agentPath } : {}),\n })\n console.log(`Installed ${paths.label}`)\n console.log(paths.plistPath)\n process.exit(0)\n }\n\n if (action === \"uninstall\") {\n const paths = uninstallLaunchAgent()\n console.log(`Uninstalled ${paths.label}`)\n process.exit(0)\n }\n\n if (action === \"status\") {\n process.stdout.write(printLaunchAgentStatus())\n process.exit(0)\n }\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n }\n\n console.error(`Unknown launch-agent action: ${action}`)\n process.exit(1)\n}\n\nif (command !== \"serve\") {\n console.error(`Unknown command: ${command}`)\n process.exit(1)\n}\n\nlet host: string\nlet port: number\ntry {\n const options = readHostAndPort()\n host = options.host\n port = options.port\n} catch (error) {\n console.error(error instanceof Error ? error.message : String(error))\n process.exit(1)\n}\n\nconst server = await startServer({\n host,\n port,\n ...(process.env.CURSOR_AGENT_PATH\n ? { agentPath: process.env.CURSOR_AGENT_PATH }\n : {}),\n})\nconsole.log(`cursor-agent-bridge listening on http://${host}:${port}`)\n\nfunction shutdown() {\n server.close(() => process.exit(0))\n}\n\nprocess.on(\"SIGINT\", shutdown)\nprocess.on(\"SIGTERM\", shutdown)\n"],"mappings":";;;;;;;;;AAAA,SAAgB,QAAQ,MAAc,UAA8B;CAClE,MAAM,QAAQ,QAAQ,KAAK,QAAQ,IAAI;CACvC,IAAI,QAAQ,GAAG,OAAO;CACtB,MAAM,QAAQ,QAAQ,KAAK,QAAQ;CACnC,IAAI,CAAC,SAAS,MAAM,WAAW,GAAG,GAChC,MAAM,IAAI,MAAM,qBAAqB,MAAM;CAC7C,OAAO;AACT;AAEA,SAAgB,UAAU,OAA2B,UAAkB;CACrE,IAAI,UAAU,KAAA,GAAW,OAAO;CAChC,MAAM,OAAO,OAAO,KAAK;CACzB,IAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAChD,MAAM,IAAI,MAAM,iBAAiB,OAAO;CAE1C,OAAO;AACT;AAEA,SAAgB,gBAAgB,cAAc,aAAa,cAAc,MAAM;CAG7E,OAAO;EAAE,MAFI,QAAQ,UAAU,QAAQ,IAAI,IAAI,KAAK;EAErC,MADF,UAAU,QAAQ,UAAU,QAAQ,IAAI,IAAI,GAAG,WAC1C;CAAE;AACtB;;;AClBA,MAAa,wBAAwB;AA2BrC,SAAgB,uBACd,UAAU,uBACV,UAAU,QAAQ,GAClB;CACA,mBAAmB,OAAO;CAC1B,OAAO,KAAK,SAAS,UAAU,GAAG,QAAQ,aAAa;AACzD;AAEA,SAAgB,aAAa,MAAc,MAAc;CACvD,OAAO,UAAU,KAAK,GAAG,KAAK;AAChC;AAEA,SAAgB,qBAAqB,SAA6B;CAChE,MAAM,UAAU,QAAQ,WAAA;CACxB,mBAAmB,OAAO;CAC1B,MAAM,UAAU,aAAa,QAAQ,MAAM,QAAQ,IAAI;CACvD,OAAO,oBAAoB,iBAAiB,OAAO,EAAE;;;mBAGpC,QAAQ;;aAEd,iBAAiB,OAAO,EAAE;;;AAGvC;AAEA,SAAgB,iBACd,SACA,UAAU,uBACV;CACA,mBAAmB,OAAO;CAC1B,MAAM,SAA4B,CAAC;CACnC,MAAM,kBAAkB,mBAAmB;CAC3C,IAAI,UAAU;CAEd,KAAK,MAAM,WAAW,QAAQ,MAAM,IAAI,GAAG;EACzC,MAAM,OAAO,QAAQ,KAAK;EAC1B,IAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,GAAG;EAEnC,MAAM,eAAe,KAAK,MAAM,YAAY;EAC5C,IAAI,cAAc;GAChB,UAAU,aAAa,MAAM;GAC7B;EACF;EAEA,MAAM,aAAa,KAAK,MAAM,gCAAgC;EAC9D,IAAI,CAAC,YAAY;EAEjB,MAAM,MAAM,WAAW,MAAM;EAC7B,MAAM,QAAQ,eAAe,WAAW,MAAM,EAAE;EAEhD,IAAI,YAAY,iBAAiB;GAC/B,IAAI,QAAQ,QAAQ,OAAO,eAAe;GAC1C,IAAI,QAAQ,YAAY,OAAO,UAAU;GACzC,IAAI,QAAQ,YAAY,OAAO,UAAU;GACzC;EACF;EAEA,IAAI,SAAS;EACb,IAAI,QAAQ,kBAAkB,OAAO,gBAAgB;EACrD,IAAI,QAAQ,SAAS,OAAO,QAAQ;CACtC;CAEA,OAAO;AACT;AAEA,SAAgB,iBACd,SACA,SACwB;CACxB,MAAM,UAAU,QAAQ,WAAA;CACxB,MAAM,kBAAkB,aAAa,QAAQ,MAAM,QAAQ,IAAI;CAC/D,MAAM,SAAS,iBAAiB,SAAS,OAAO;CAChD,MAAM,SAAmB,CAAC;CAE1B,IAAI,OAAO,kBAAkB,SAC3B,OAAO,KACL,6BAA6B,QAAQ,GACnC,OAAO,gBACH,YAAY,OAAO,cAAc,KACjC,uBAER;CAGF,IAAI,OAAO,YAAY,iBACrB,OAAO,KACL,uBAAuB,gBAAgB,GACrC,OAAO,UAAU,YAAY,OAAO,QAAQ,KAAK,uBAErD;CAGF,IAAI,OAAO,YAAY,aACrB,OAAO,KACL,iCACE,OAAO,UAAU,YAAY,OAAO,QAAQ,KAAK,uBAErD;CAGF,OAAO;EAAE,IAAI,OAAO,WAAW;EAAG;CAAO;AAC3C;AAEA,eAAsB,iBACpB,SAIiC;CACjC,IAAI;CAEJ,IAAI;EACF,WAAW,MAAM,SAAS,QAAQ,UAAU,MAAM;CACpD,SAAS,OAAO;EACd,IAAK,MAAgC,SAAS,UAAU,MAAM;CAChE;CAEA,IAAI,aAAa,KAAA,GAAW;EAC1B,MAAM,MAAM,QAAQ,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;EAC1D,MAAM,UAAU,QAAQ,UAAU,qBAAqB,OAAO,GAAG,MAAM;EACvE,OAAO;GAAE,MAAM,QAAQ;GAAU,SAAS;GAAM,SAAS;EAAM;CACjE;CAEA,MAAM,SAAS,iBAAiB,UAAU,OAAO;CACjD,IAAI,WAAW,QAAQ,MAAM,IAAI,MAAM,OAAO,KAAK;CAEnD,IAAI,CAAC,OAAO,SACV,OAAO;EAAE,MAAM,QAAQ;EAAU,SAAS;EAAO,SAAS;CAAM;CAGlE,MAAM,UAAU,QAAQ,UAAU,OAAO,SAAS,MAAM;CACxD,OAAO;EAAE,MAAM,QAAQ;EAAU,SAAS;EAAO,SAAS;CAAK;AACjE;AAEA,SAAS,iBACP,UACA,SACA;CACA,MAAM,UAAU,QAAQ,WAAA;CACxB,mBAAmB,OAAO;CAC1B,MAAM,kBAAkB,mBAAmB;CAC3C,MAAM,WAAW,qBAAqB,OAAO;CAC7C,MAAM,SAAS,iBAAiB,UAAU,OAAO;CAEjD,IACE,OAAO,iBACP,OAAO,kBAAkB,WACzB,CAAC,QAAQ,OAET,OAAO,EACL,OAAO,sBAAsB,OAAO,cAAc,0CAA0C,QAAQ,IACtG;CAGF,MAAM,QAAQ,SAAS,MAAM,IAAI;CACjC,MAAM,SAAmB,CAAC;CAC1B,IAAI,UAAU;CACd,IAAI,oBAAoB;CACxB,IAAI,mBAAmB;CACvB,IAAI,WAAW;CACf,IAAI,qBAAqB;CACzB,MAAM,sCAAsB,IAAI,IAAY;CAE5C,KAAK,MAAM,WAAW,OAAO;EAC3B,MAAM,UAAU,QAAQ,KAAK;EAC7B,MAAM,eAAe,QAAQ,MAAM,YAAY;EAC/C,IAAI,cAAc;GAChB,IAAI,mBAAmB,0BAA0B;GACjD,UAAU,aAAa,MAAM;GAC7B,oBAAoB,YAAY;GAChC,IAAI,mBAAmB,qBAAqB;GAC5C,OAAO,KAAK,OAAO;GACnB;EACF;EAEA,MAAM,aAAa,QAAQ,MAAM,gCAAgC;EACjE,IAAI,CAAC,YAAY;GACf,OAAO,KAAK,OAAO;GACnB;EACF;EAEA,MAAM,MAAM,WAAW,MAAM;EAE7B,IAAI,CAAC,SAAS;GACZ,IAAI,QAAQ,kBAAkB;IAC5B,mBAAmB;IACnB,OAAO,KAAK,oBAAoB,iBAAiB,OAAO,GAAG;IAC3D;GACF;GACA,IAAI,QAAQ,SAAS;IACnB,WAAW;IACX,IAAI,OAAO,UAAU,KAAA,KAAa,QAAQ,OACxC,OAAO,KAAK,kBAAgB;SAE5B,OAAO,KAAK,OAAO;IAErB;GACF;EACF;EAEA,IAAI,mBAAmB;GACrB,IAAI,QAAQ,QAAQ;IAClB,oBAAoB,IAAI,MAAM;IAC9B,OAAO,KAAK,gCAA8B;IAC1C;GACF;GACA,IAAI,QAAQ,YAAY;IACtB,oBAAoB,IAAI,UAAU;IAClC,OAAO,KACL,cAAc,iBAAiB,aAAa,QAAQ,MAAM,QAAQ,IAAI,CAAC,GACzE;IACA;GACF;GACA,IAAI,QAAQ,YAAY;IACtB,oBAAoB,IAAI,UAAU;IAClC,OAAO,KAAK,0BAAwB;IACpC;GACF;EACF;EAEA,OAAO,KAAK,OAAO;CACrB;CAEA,IAAI,mBAAmB,0BAA0B;CAEjD,MAAM,kBAA4B,CAAC;CACnC,IAAI,CAAC,kBACH,gBAAgB,KAAK,oBAAoB,iBAAiB,OAAO,GAAG;CACtE,IAAI,CAAC,UAAU,gBAAgB,KAAK,kBAAgB;CAEpD,IAAI,UAAU,OAAO,KAAK,IAAI,CAAC,CAAC,QAAQ;CACxC,IAAI,gBAAgB,SAAS,GAC3B,UAAU,GAAG,gBAAgB,KAAK,IAAI,EAAE,IAAI;CAG9C,IAAI,CAAC,oBAAoB;EACvB,MAAM,gBAAgB,SAAS,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI;EAC7D,UAAU,GAAG,QAAQ,MAAM,cAAc;CAC3C;CAEA,MAAM,UAAU,cAAc,OAAO,MAAM,cAAc,QAAQ;CACjE,OAAO;EAAE,SAAS,GAAG,QAAQ,QAAQ,EAAE;EAAK;CAAQ;CAEpD,SAAS,4BAA4B;EACnC,IAAI,CAAC,oBAAoB,IAAI,MAAM,GACjC,OAAO,KAAK,gCAA8B;EAE5C,IAAI,CAAC,oBAAoB,IAAI,UAAU,GACrC,OAAO,KACL,cAAc,iBAAiB,aAAa,QAAQ,MAAM,QAAQ,IAAI,CAAC,GACzE;EAEF,IAAI,CAAC,oBAAoB,IAAI,UAAU,GACrC,OAAO,KAAK,0BAAwB;CAExC;AACF;AAEA,SAAS,mBAAmB,SAAiB;CAC3C,IAAI,mBAAmB,KAAK,OAAO,GAAG;CACtC,MAAM,IAAI,MACR,4EACF;AACF;AAEA,SAAS,iBAAiB,OAAe;CACvC,OAAO,IAAI,MACR,WAAW,MAAM,MAAM,CAAC,CACxB,WAAW,MAAK,MAAK,CAAC,CACtB,WAAW,MAAM,KAAK,CAAC,CACvB,WAAW,KAAM,KAAK,CAAC,CACvB,WAAW,MAAM,KAAK,CAAC,CACvB,WAAW,MAAM,KAAK,CAAC,CACvB,WAAW,MAAM,KAAK,EAAE;AAC7B;AAEA,SAAS,cAAc,SAAiB;CACtC,OAAO,QAAQ,QAAQ,SAAS,IAAI,CAAC,CAAC,QAAQ;AAChD;AAEA,SAAS,eAAe,KAAa;CACnC,MAAM,UAAU,uBAAuB,GAAG,CAAC,CAAC,KAAK;CACjD,IAAI,QAAQ,WAAW,IAAG,KAAK,QAAQ,SAAS,IAAG,GACjD,OAAO,mBAAmB,QAAQ,MAAM,GAAG,EAAE,CAAC;CAEhD,IAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GACjD,OAAO,QAAQ,MAAM,GAAG,EAAE;CAE5B,OAAO;AACT;AAEA,SAAS,mBAAmB,OAAe;CACzC,OAAO,MAAM,QACX,oBACC,QAAQ,aACN;EACC,MAAK;EACL,MAAM;EACN,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;EACH,GAAG;CACL,EAAA,CAAG,YAAY,OACnB;AACF;AAEA,SAAS,uBAAuB,KAAa;CAC3C,IAAI;CACJ,KAAK,IAAI,QAAQ,GAAG,QAAQ,IAAI,QAAQ,SAAS,GAAG;EAClD,MAAM,OAAO,IAAI;EACjB,KAAK,SAAS,QAAO,SAAS,QAAQ,IAAI,QAAQ,OAAO,MAAM;GAC7D,QAAQ,UAAU,OAAO,KAAA,IAAa,SAAS;GAC/C;EACF;EAEA,IAAI,CAAC,SAAS,SAAS,KACrB,OAAO,IAAI,MAAM,GAAG,KAAK;CAE7B;CAEA,OAAO;AACT;;;ACvVA,MAAMA,kBAAgB,UAAU,QAAQ;AA6BxC,eAAsB,UAAU,SAAwB;CACtD,MAAM,SAAwB,CAAC;CAC/B,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,aAAa,QAAQ,cAAcA;CACzC,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,YACJ,QAAQ,aAAa,QAAQ,IAAI,qBAAqB;CACxD,MAAM,UAAU,QAAQ,WAAA;CACxB,MAAM,kBACJ,QAAQ,mBAAmB,uBAAuB,OAAO;CAE3D,OAAO,KACL,iBAAiB,QAAQ,oBAAA,QAAwC,IAAI,CACvE;CACA,OAAO,KAAK;EACV,MAAM;EACN,IAAI;EACJ,SAAS,uBAAuBC;CAClC,CAAC;CAED,MAAM,aAAa,MAAM,qBAAqB,WAAW,UAAU;CACnE,OAAO,KAAK,UAAU;CAEtB,IAAI,WAAW,IACb,OAAO,KAAK,MAAM,gBAAgB,WAAW,QAAQ,MAAM,CAAC;CAG9D,OAAO,KAAK,MAAM,kBAAkB,QAAQ,MAAM,QAAQ,MAAM,OAAO,CAAC;CAExE,IAAI,CAAC,QAAQ,iBACX,OAAO,KACL,MAAM,qBAAqB;EACzB;EACA,MAAM,QAAQ;EACd,MAAM,QAAQ;EACd;EACA;CACF,CAAC,CACH;CAGF,OAAO;EACL,IAAI,OAAO,OAAO,UAAU,MAAM,EAAE;EACpC;CACF;AACF;AAEA,SAAgB,mBAAmB,QAGhC;CACD,MAAM,QAAQ,OAAO,OAAO,KAAK,UAAU;EACzC,MAAM,SAAS,MAAM,KAAK,MAAM;EAChC,MAAM,OAAO,MAAM,OAAO,SAAS,MAAM,SAAS;EAClD,OAAO,GAAG,OAAO,GAAG,MAAM,KAAK,IAAI,MAAM,UAAU;CACrD,CAAC;CAED,MAAM,KAAK,EAAE;CACb,MAAM,KACJ,OAAO,KACH,sEACA,gEACN;CAEA,OAAO,GAAG,MAAM,KAAK,IAAI,EAAE;AAC7B;AAEA,SAAS,iBAAiB,eAAoC;CAC5D,MAAM,UAAU,QAAQ,QAAQ,MAAM,CAAC;CACvC,MAAM,UAAU,wBAAwB,aAAa;CACrD,MAAM,KAAK,mBAAmB,SAAS,OAAO,KAAK;CAEnD,OAAO,KACH;EACE,MAAM;EACN;EACA,SAAS,QAAQ,QAAQ,aAAa;CACxC,IACA;EACE,MAAM;EACN;EACA,SAAS,QAAQ,QAAQ,oBAAoB;EAC7C,MAAM,gBAAgB,QAAQ;CAChC;AACN;AAEA,eAAe,qBACb,WACA,YACsB;CACtB,IAAI;EACF,MAAM,WAAW,WAAW,CAAC,QAAQ,GAAG,EAAE,SAAS,IAAM,CAAC;EAC1D,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,6BAA6B;EACxC;CACF,SAAS,OAAO;EAGd,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAJA,iBAAiB,QAAQ,MAAM,UAAU;GAKzC,MAAM;EACR;CACF;AACF;AAEA,eAAe,gBACb,WACA,SAAS,IAAI,aAAa,EAAE,UAAU,CAAC,GACjB;CACtB,IAAI;EACF,MAAM,SAAS,MAAM,OAAO,WAAW,EACrC,SAAS,KACX,CAAC;EACD,IAAI,OAAO,WAAW,GACpB,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS;GACT,MAAM;EACR;EAGF,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,8BAA8B,OAAO,OAAO;EACvD;CACF,SAAS,OAAO;EAGd,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAJA,iBAAiB,QAAQ,MAAM,UAAU;GAKzC,MAAM;EACR;CACF;AACF;AAEA,eAAe,kBACb,MACA,MACA,SACsB;CACtB,MAAM,MAAM,UAAU,KAAK,GAAG,KAAK;CACnC,IAAI;EACF,MAAM,WAAW,MAAM,QAAQ,KAAK,EAAE,QAAQ,YAAY,QAAQ,GAAK,EAAE,CAAC;EAC1E,IAAI,CAAC,SAAS,IACZ,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,GAAG,IAAI,iBAAiB,SAAS;GAC1C,MAAM;EACR;EAGF,MAAM,UAAW,MAAM,SAAS,KAAK;EACrC,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,QAAQ,UACb,0BAA0B,IAAI,YAAY,QAAQ,QAAQ,KAC1D,0BAA0B;EAChC;CACF,SAAS,OAAO;EAGd,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAJA,iBAAiB,QAAQ,MAAM,UAAU;GAKzC,MAAM;EACR;CACF;AACF;AAEA,eAAe,qBAAqB,SAMX;CACvB,IAAI;EAEF,MAAM,SAAS,iBAAiB,MADV,QAAQ,WAAW,QAAQ,iBAAiB,MAAM,GAC/B;GACvC,MAAM,QAAQ;GACd,MAAM,QAAQ;GACd,SAAS,QAAQ;EACnB,CAAC;EAED,IAAI,OAAO,IACT,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,iCAAiC,QAAQ;EACpD;EAGF,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,OAAO,OAAO,KAAK,IAAI;GAChC,MAAM;EACR;CACF,SAAS,OAAO;EACd,IAAK,MAAgC,SAAS,UAC5C,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAAS,6BAA6B,QAAQ;GAC9C,MAAM;EACR;EAKF,OAAO;GACL,MAAM;GACN,IAAI;GACJ,SAJA,iBAAiB,QAAQ,MAAM,UAAU;GAKzC,MAAM;EACR;CACF;AACF;AAEA,SAAS,wBAAwB,OAAe;CAC9C,MAAM,QAAQ,MAAM,MAAM,0BAA0B;CACpD,IAAI,CAAC,OAAO,OAAO;CACnB,OAAO,GAAG,MAAM,GAAG,GAAG,MAAM,GAAG,GAAG,MAAM,MAAM;AAChD;AAEA,SAAS,mBAAmB,MAAc,OAAe;CACvD,MAAM,WAAW,UACf,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,SAAS,OAAO,SAAS,MAAM,EAAE,KAAK,CAAC;CAC/D,MAAM,CAAC,YAAY,GAAG,YAAY,GAAG,YAAY,KAAK,QAAQ,IAAI;CAClE,MAAM,CAAC,aAAa,GAAG,aAAa,GAAG,aAAa,KAAK,QAAQ,KAAK;CAEtE,IAAI,cAAc,YAAY,OAAO,YAAY;CACjD,IAAI,cAAc,YAAY,OAAO,YAAY;CACjD,OAAO,YAAY;AACrB;;;AClRA,MAAM,eAAe;AACrB,MAAM,gBAAgB,KAAK,QAAQ,GAAG,UAAU,MAAM;AAiBtD,SAAgB,oBAAoB,QAAQ,cAAgC;CAC1E,OAAO;EACL;EACA,WAAW,KAAK,QAAQ,GAAG,WAAW,gBAAgB,GAAG,MAAM,OAAO;EACtE,YAAY,KAAK,eAAe,yBAAyB;EACzD,YAAY,KAAK,eAAe,6BAA6B;CAC/D;AACF;AAEA,SAAgB,uBAAuB,SAA6B;CAClE,MAAM,QAAQ,QAAQ,SAAS;CAC/B,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,OAAO,QAAQ,QAAQ;CAC7B,MAAM,QAAQ,oBAAoB,KAAK;CACvC,MAAM,OAAO;EACX,QAAQ,QAAQ,OAAO;EACvB;EACA;EACA;EACA;EACA,OAAO,IAAI;CACb;CACA,MAAM,MAA8B,EAClC,MAAM;EACJ,QAAQ,QAAQ,QAAQ,OAAO,CAAC;EAChC,KAAK,QAAQ,GAAG,UAAU,KAAK;EAC/B;EACA;EACA;EACA;EACA;EACA;CACF,CAAC,CAAC,KAAK,GAAG,EACZ;CAEA,IAAI,QAAQ,WACV,IAAI,oBAAoB,QAAQ;CAGlC,OAAO;;;;;YAKG,YAAY,KAAK,EAAE;;;;EAI7B,KAAK,KAAK,QAAQ,eAAe,YAAY,GAAG,EAAE,UAAU,CAAC,CAAC,KAAK,IAAI,EAAE;;;;;EAKzE,OAAO,QAAQ,GAAG,CAAC,CAClB,KACE,CAAC,KAAK,WACL,YAAY,YAAY,GAAG,EAAE,sBAAsB,YAAY,KAAK,EAAE,UAC1E,CAAC,CACA,KAAK,IAAI,EAAE;;;;;;;;;;YAUF,YAAY,MAAM,UAAU,EAAE;;;YAG9B,YAAY,MAAM,UAAU,EAAE;;;;AAI1C;AAEA,SAAgB,mBAAmB,SAA6B;CAC9D,YAAY;CAEZ,MAAM,QAAQ,oBADA,QAAQ,SAAS,YACQ;CACvC,UAAU,QAAQ,MAAM,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;CACvD,UAAU,eAAe,EAAE,WAAW,KAAK,CAAC;CAE5C,IAAI,WAAW,MAAM,SAAS,GAC5B,QAAQ,MAAM,SAAS;CAGzB,cAAc,MAAM,WAAW,uBAAuB,OAAO,CAAC;CAC9D,UAAU,MAAM,WAAW,GAAK;CAChC,aAAa,aAAa;EAAC;EAAa,gBAAgB;EAAG,MAAM;CAAS,GAAG,EAC3E,OAAO,OACT,CAAC;CACD,OAAO;AACT;AAEA,SAAgB,qBAAqB,QAAQ,cAAc;CACzD,YAAY;CACZ,MAAM,QAAQ,oBAAoB,KAAK;CACvC,QAAQ,MAAM,SAAS;CACvB,OAAO,MAAM,WAAW,EAAE,OAAO,KAAK,CAAC;CACvC,OAAO;AACT;AAEA,SAAgB,uBAAuB,QAAQ,cAAc;CAC3D,YAAY;CACZ,OAAO,aAAa,aAAa,CAAC,SAAS,GAAG,gBAAgB,EAAE,GAAG,OAAO,GAAG,EAC3E,UAAU,OACZ,CAAC;AACH;AAEA,SAAS,QAAQ,WAAmB;CAClC,IAAI;EACF,aAAa,aAAa;GAAC;GAAW,gBAAgB;GAAG;EAAS,GAAG,EACnE,OAAO,OACT,CAAC;CACH,QAAQ,CAER;AACF;AAEA,SAAS,kBAAkB;CACzB,OAAO,OAAO,QAAQ,SAAS,KAAK,aAAa,MAAM,CAAC,IAAI,GAAG,EAAE,UAAU,OAAO,CAAC,CAAC,CAAC,KAAK;AAC5F;AAEA,SAAS,cAAc;CACrB,IAAI,QAAQ,aAAa,UACvB,MAAM,IAAI,MAAM,oDAAoD;AAExE;AAEA,SAAS,YAAY,OAAe;CAClC,OAAO,MACJ,WAAW,KAAK,OAAO,CAAC,CACxB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,KAAK,MAAM,CAAC,CACvB,WAAW,MAAK,QAAQ,CAAC,CACzB,WAAW,KAAK,QAAQ;AAC7B;;;AClKA,MAAM,gBAAgB,UAAU,QAAQ;AAExC,MAAa,eAAe;AAC5B,MAAa,uBAAuB,8BAA8B,aAAa;AAC/E,MAAM,sBAAsB;AAkC5B,SAAgB,cAAc,MAAc,OAA2B;CACrE,MAAM,WAAW,UAAkB;EACjC,MAAM,CAAC,QAAQ,GAAG,QAAQ,GAAG,QAAQ,KAAK,MACvC,MAAM,GAAG,CAAC,CACV,KAAK,SAAS,OAAO,SAAS,MAAM,EAAE,KAAK,CAAC;EAC/C,OAAO;GAAC;GAAO;GAAO;EAAK;CAC7B;CACA,MAAM,CAAC,WAAW,WAAW,aAAa,QAAQ,IAAI;CACtD,MAAM,CAAC,YAAY,YAAY,cAAc,QAAQ,KAAK;CAE1D,IAAI,cAAc,YAChB,OAAO,YAAY,aAAa,KAAK;CAEvC,IAAI,cAAc,YAChB,OAAO,YAAY,aAAa,KAAK;CAEvC,IAAI,cAAc,YAChB,OAAO,YAAY,aAAa,KAAK;CAEvC,OAAO;AACT;AAEA,eAAsB,mBAAmB,SAIrB;CAClB,MAAM,cAAc,SAAS,eAAe;CAC5C,MAAM,UAAU,SAAS,WAAW;CACpC,MAAM,YAAY,SAAS,aAAa;CACxC,MAAM,aAAa,IAAI,gBAAgB;CACvC,MAAM,UAAU,iBAAiB,WAAW,MAAM,GAAG,SAAS;CAE9D,IAAI;EACF,MAAM,WAAW,MAAM,QAAQ,aAAa,EAAE,QAAQ,WAAW,OAAO,CAAC;EACzE,IAAI,CAAC,SAAS,IACZ,MAAM,IAAI,MAAM,qBAAqB,SAAS,QAAQ;EAGxD,MAAM,UAAW,MAAM,SAAS,KAAK;EACrC,IAAI,CAAC,QAAQ,SACX,MAAM,IAAI,MAAM,mCAAmC;EAErD,OAAO,QAAQ;CACjB,UAAU;EACR,aAAa,OAAO;CACtB;AACF;AAEA,eAAe,cACb,SACA,YACkB;CAClB,IAAI;EACF,MAAM,WAAW,SAAS,CAAC,OAAO,CAAC;EACnC,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,eAAsB,qBACpB,YACA,aAAyB,eACA;CACzB,IAAI,eAAe,OAAO,OAAO;CACjC,IAAI,eAAe,QAAQ,OAAO;CAElC,IAAI,CAAE,MAAM,cAAc,QAAQ,UAAU,GAC1C,OAAO;CAGT,IAAI;EACF,MAAM,WAAW,QAAQ;GAAC;GAAQ;GAAM;GAAc;EAAQ,GAAG,EAC/D,KAAK,QAAQ,IACf,CAAC;EACD,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;AAEA,SAAgB,oBACd,SACA,QACqC;CAGrC,MAAM,cAAc,GAAG,eADrB,WAAW,WAAW,YAAY,IAAI,OAAO,QAAQ,MAAM,EAAE;CAG/D,IAAI,YAAY,QACd,OAAO;EAAE,SAAS;EAAQ,MAAM;GAAC;GAAO;GAAM;EAAW;CAAE;CAG7D,OAAO;EAAE,SAAS;EAAO,MAAM;GAAC;GAAW;GAAM;EAAW;CAAE;AAChE;AAEA,SAAS,uBAAuB,UAAwC;CACtE,SAAS,mBAAmB;CAC5B,SAAS,iBAAiB,aAAa,QAAQ;CAC/C,SAAS,oBAAoB,aAAa,QAAQ;AACpD;AAEA,eAAe,qBACb,QACA,aACA,SACiB;CACjB,IAAI,WAAW,UACb,OAAO,mBAAmB;EAAE;EAAa;CAAQ,CAAC;CAEpD,OAAO,OAAO,QAAQ,MAAM,EAAE;AAChC;AAEA,eAAe,WACb,SACA,QACA,SACiB;CACjB,MAAM,EAAE,SAAS,SAAS,oBAAoB,SAAS,MAAM;CAC7D,OAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,QAAQ,QAAQ,SAAS,MAAM;GACnC,OAAO;GACP,KAAK,QAAQ;EACf,CAAC;EAED,MAAM,GAAG,SAAS,MAAM;EACxB,MAAM,GAAG,UAAU,SAAS,QAAQ,QAAQ,CAAC,CAAC;CAChD,CAAC;AACH;AAEA,eAAsB,WAAW,SAA0C;CACzE,MAAM,MAAM,QAAQ,OAAO,QAAQ;CACnC,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAC7C,MAAM,YAAY,QAAQ,aAAa;CACvC,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,oBAAoB,QAAQ,WAAW;CAC7C,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,UAAU,QAAQ,WAAW;CACnC,MAAM,UACJ,QAAQ,aACN,SAAS,MAAM,iBAAiB,MAAM,SAAS,MAAM,YAAY;CACrE,MAAM,aAAa,QAAQ,cAAc;CACzC,MAAM,WAAW,QAAQ,YAAY;CAErC,IAAI;CACJ,IAAI;EACF,gBAAgB,MAAM,qBAAqB,QAAQ,aAAa,OAAO;CACzE,SAAS,OAAO;EACd,SACE,gCAAgC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GACvF;EACA,uBAAuB,QAAQ;EAC/B,OAAO;CACT;CAGA,IADmB,cAAc,QAAQ,gBAAgB,aAC5C,KAAK,GAAG;EACnB,IAAI,GAAG,aAAa,kBAAkB,QAAQ,eAAe,EAAE;EAC/D,OAAO;CACT;CAEA,IAAI,WAAW;EACb,IAAI,qBAAqB,QAAQ,eAAe,MAAM,eAAe;EACrE,OAAO;CACT;CAEA,IAAI;CACJ,UAAU,MAAM,qBAAqB,mBAAmB,UAAU;CAElE,IAAI,cAAc,aAAa,GAAG,cAAc,OAAO,QAAQ,IAAI;CACnE,IAAI;EACF,MAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,OAAO;EAC1D,IAAI,aAAa,GAAG;GAClB,SAAS,GAAG,QAAQ,iCAAiC,UAAU;GAC/D,uBAAuB,QAAQ;GAC/B,OAAO;EACT;CACF,SAAS,OAAO;EACd,SACE,mBAAmB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GAC1E;EACA,uBAAuB,QAAQ;EAC/B,OAAO;CACT;CAEA,IAAI,aAAa,aAAa,GAAG,eAAe;CAChD,IAAI,4DAA4D;CAEhE,MAAM,mBAAmB,oBAAoB,CAAC,CAAC;CAC/C,IAAI,SAAS,gBAAgB,GAC3B,IACE,8FACF;CAGF,OAAO;AACT;;;ACzNA,MAAM,UACJ,QAAQ,KAAK,MAAM,CAAC,QAAQ,KAAK,EAAE,EAAE,WAAW,GAAG,IAC/C,QAAQ,KAAK,KACb;AAEN,IACE,YAAY,UACZ,QAAQ,KAAK,SAAS,QAAQ,KAC9B,QAAQ,KAAK,SAAS,IAAI,GAC1B;CACA,QAAQ,IAAI;;;;;;;;;;;;;;;;;;CAkBb;CACC,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,YAAY,aAAa,QAAQ,KAAK,SAAS,WAAW,GAAG;CAC/D,QAAQ,IAAIC,OAAmB;CAC/B,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,YAAY,WAAW;CACzB,MAAM,YAAY,QAAQ,KAAK,SAAS,SAAS;CACjD,MAAM,SAAS,QAAQ,YAAY,QAAQ,KAAK;CAChD,MAAM,UAAU,QAAQ,aAAa,MAAM,KAAK;CAEhD,IAAI,YAAY,UAAU,YAAY,SAAS,YAAY,QAAQ;EACjE,QAAQ,MAAM,kDAAkD;EAChE,QAAQ,KAAK,CAAC;CAChB;CAEA,MAAM,WAAW,MAAM,WAAW;EAChC,gBAAgBA;EAChB;EACA;EACA;CACF,CAAC;CACD,QAAQ,KAAK,QAAQ;AACvB;AAEA,IAAI,YAAY,UACd,IAAI;CACF,MAAM,EAAE,MAAM,SAAS,gBAAgB;CACvC,MAAM,UACJ,QAAQ,aAAA,QAAkC,KAAA;CAC5C,MAAM,kBAAkB,QAAQ,UAAU,KAAA,CAAS;CACnD,MAAM,SAAS,MAAM,UAAU;EAC7B;EACA;EACA;EACA,iBAAiB,QAAQ,KAAK,SAAS,qBAAqB;EAC5D,GAAI,QAAQ,IAAI,oBACZ,EAAE,WAAW,QAAQ,IAAI,kBAAkB,IAC3C,CAAC;EACL,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;CAC/C,CAAC;CACD,QAAQ,OAAO,MAAM,mBAAmB,MAAM,CAAC;CAC/C,QAAQ,KAAK,OAAO,KAAK,IAAI,CAAC;AAChC,SAAS,OAAO;CACd,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CACpE,QAAQ,KAAK,CAAC;AAChB;AAGF,IAAI,YAAY,UAAU;CACxB,MAAM,SAAS,QAAQ,KAAK,MAAM;CAClC,IAAI;EACF,MAAM,EAAE,MAAM,SAAS,gBAAgB;EACvC,MAAM,UACJ,QAAQ,aAAA,QAAkC,KAAA;EAC5C,MAAM,WACJ,QAAQ,UAAU,KAAA,CAAS,KAAK,uBAAuB,OAAO;EAEhE,IAAI,WAAW,SAAS;GACtB,QAAQ,OAAO,MAAM,qBAAqB;IAAE;IAAM;IAAM;GAAQ,CAAC,CAAC;GAClE,QAAQ,MAAM,qCAAqC,SAAS;GAC5D,QAAQ,KAAK,CAAC;EAChB;EAEA,IAAI,WAAW,SAAS;GAEtB,MAAM,SAAS,iBAAiB,MADV,SAAS,UAAU,MAAM,GACN;IAAE;IAAM;IAAM;GAAQ,CAAC;GAChE,IAAI,OAAO,IAAI;IACb,QAAQ,IAAI,+BAA+B,UAAU;IACrD,QAAQ,KAAK,CAAC;GAChB;GAEA,KAAK,MAAM,SAAS,OAAO,QACzB,QAAQ,MAAM,KAAK;GAErB,QAAQ,KAAK,CAAC;EAChB;EAEA,IAAI,WAAW,SAAS;GACtB,MAAM,SAAS,MAAM,iBAAiB;IACpC;IACA;IACA;IACA;IACA,OAAO,QAAQ,KAAK,SAAS,SAAS;GACxC,CAAC;GAED,IAAI,OAAO,SACT,QAAQ,IAAI,2BAA2B,OAAO,MAAM;QAC/C,IAAI,OAAO,SAChB,QAAQ,IAAI,2BAA2B,OAAO,MAAM;QAEpD,QAAQ,IAAI,sCAAsC,OAAO,MAAM;GAGjE,QAAQ,IAAI,qCAAqC,SAAS;GAC1D,QAAQ,KAAK,CAAC;EAChB;CACF,SAAS,OAAO;EACd,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EACpE,QAAQ,KAAK,CAAC;CAChB;CAEA,QAAQ,MAAM,0BAA0B,QAAQ;CAChD,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,YAAY,UACd,IAAI;CAMF,MAAM,SAAS,MAAM,IALF,aAAa,EAC9B,GAAI,QAAQ,IAAI,oBACZ,EAAE,WAAW,QAAQ,IAAI,kBAAkB,IAC3C,CAAC,EACP,CAC0B,CAAC,CAAC,WAAW,EACrC,SAAS,QAAQ,KAAK,SAAS,WAAW,EAC5C,CAAC;CAED,IAAI,QAAQ,KAAK,SAAS,QAAQ,GAAG;EACnC,QAAQ,IAAI,KAAK,UAAU,kBAAkB,MAAM,GAAG,MAAM,CAAC,CAAC;EAC9D,QAAQ,KAAK,CAAC;CAChB;CAEA,KAAK,MAAM,SAAS,QAClB,QAAQ,IAAI,MAAM,EAAE;CAEtB,QAAQ,KAAK,CAAC;AAChB,SAAS,OAAO;CACd,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CACpE,QAAQ,KAAK,CAAC;AAChB;AAGF,IAAI,YAAY,gBAAgB;CAC9B,MAAM,SAAS,QAAQ,KAAK,MAAM;CAClC,IAAI;EACF,IAAI,WAAW,WAAW;GACxB,MAAM,EAAE,MAAM,SAAS,gBAAgB;GACvC,MAAM,YAAY,QAAQ,gBAAgB,QAAQ,IAAI,iBAAiB;GACvE,MAAM,QAAQ,mBAAmB;IAC/B,SAAS,QAAQ,KAAK,MAAM;IAC5B;IACA;IACA,GAAI,YAAY,EAAE,UAAU,IAAI,CAAC;GACnC,CAAC;GACD,QAAQ,IAAI,aAAa,MAAM,OAAO;GACtC,QAAQ,IAAI,MAAM,SAAS;GAC3B,QAAQ,KAAK,CAAC;EAChB;EAEA,IAAI,WAAW,aAAa;GAC1B,MAAM,QAAQ,qBAAqB;GACnC,QAAQ,IAAI,eAAe,MAAM,OAAO;GACxC,QAAQ,KAAK,CAAC;EAChB;EAEA,IAAI,WAAW,UAAU;GACvB,QAAQ,OAAO,MAAM,uBAAuB,CAAC;GAC7C,QAAQ,KAAK,CAAC;EAChB;CACF,SAAS,OAAO;EACd,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;EACpE,QAAQ,KAAK,CAAC;CAChB;CAEA,QAAQ,MAAM,gCAAgC,QAAQ;CACtD,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,YAAY,SAAS;CACvB,QAAQ,MAAM,oBAAoB,SAAS;CAC3C,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI;AACJ,IAAI;AACJ,IAAI;CACF,MAAM,UAAU,gBAAgB;CAChC,OAAO,QAAQ;CACf,OAAO,QAAQ;AACjB,SAAS,OAAO;CACd,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;CACpE,QAAQ,KAAK,CAAC;AAChB;AAEA,MAAM,SAAS,MAAM,YAAY;CAC/B;CACA;CACA,GAAI,QAAQ,IAAI,oBACZ,EAAE,WAAW,QAAQ,IAAI,kBAAkB,IAC3C,CAAC;AACP,CAAC;AACD,QAAQ,IAAI,2CAA2C,KAAK,GAAG,MAAM;AAErE,SAAS,WAAW;CAClB,OAAO,YAAY,QAAQ,KAAK,CAAC,CAAC;AACpC;AAEA,QAAQ,GAAG,UAAU,QAAQ;AAC7B,QAAQ,GAAG,WAAW,QAAQ"}
|
package/dist/index.d.mts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/adapter/messages.ts","../src/adapter/models.ts","../src/cursor/runner.ts","../src/server.ts"],"mappings":";;;KAAY,QAAA;AAAA,UAEK,WAAA;EACf,IAAA,EAAM,QAAA;EACN,OAAA,WAEI,KAAK;IACH,IAAA;IACA,IAAA;IACA,UAAA;IACA,WAAA;EAAA;AAAA;AAAA,UAIS,qBAAA;EACf,KAAA;EACA,QAAA,EAAU,WAAW;EACrB,MAAA;EACA,WAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,UAGe,gBAAA;EACf,KAAA;EACA,KAAA;EACA,YAAA;EACA,MAAA;EACA,WAAA;EACA,KAAA;EACA,iBAAA;AAAA;AAAA,UAGe,WAAA;EACf,EAAA;EACA,IAAI;AAAA;AAAA,UAGW,gBAAA;EACf,KAAA;EACA,MAAA;EACA,GAAA;EACA,MAAA,GAAS,WAAW;AAAA;AAAA,UAGL,eAAA;EACf,IAAA;EACA,KAAK;AAAA;AAAA,UAGU,eAAA;EACf,OAAA,IAAW,IAAA;EACX,OAAA,IAAW,KAAA;AAAA;AAAA,UAGI,YAAA;EACf,IAAA;EACA,IAAA;EACA,SAAA;EACA,UAAA;EACA,YAAA;AAAA;;;iBCjDc,gBAAA,CAAiB,QAAuB,EAAb,WAAW;AAAA,iBAuCtC,mBAAA,CAAoB,OAAA,EAAS,gBAAA,GAAmB,WAAW;AAAA,iBAyC3D,cAAA,CAAe,KAAyB;;;iBCzFxC,mBAAA,CAAoB,MAAA,WAAiB,WAAW;AAAA,iBAWhD,iBAAA,CAAkB,MAAA,EAAQ,WAAW;;;;;;;;;iBAarC,mBAAA,CAAoB,MAAA,EAAQ,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UCjBtC,mBAAA;EACf,SAAA;EACA,UAAA;EACA,SAAA;EACA,gBAAA;EACA,iBAAA;EACA,IAAA;AAAA;AAAA,cAOW,YAAA;EAAA,SACF,SAAA;EAAA,SACA,UAAA;EAAA,SACA,SAAA;EAAA,SACA,gBAAA;EAAA,SACA,iBAAA;EAAA,SACA,IAAA;EAAA,QACD,UAAA;EAAA,QACA,UAAA;EAAA,iBACS,QAAA;EAAA,iBACA,cAAA;cAEL,OAAA,GAAS,mBAAA;EAgBf,UAAA,CACJ,OAAA;IAAW,OAAA;EAAA,IACV,OAAA,CAAQ,WAAA;EA4BL,GAAA,CACJ,OAAA,EAAS,gBAAA,EACT,MAAA,GAAQ,eAAA,GACP,OAAA,CAAQ,eAAA;EAUX,QAAA;EAAA,QAIQ,gBAAA;EAAA,QAmCA,aAAA;AAAA;;;iBC7FY,WAAA,CAAY,MAAA,GAAQ,YAAA,GAAiB,OAAA,CAAA,IAAA,CAAA,MAAA,QAAA,IAAA,CAAA,eAAA,SAAA,IAAA,CAAA,cAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server-Bk7ol2lA.mjs","names":["packageJson.version"],"sources":["../src/adapter/messages.ts","../src/adapter/models.ts","../src/cursor/runner.ts","../package.json","../src/adapter/openai.ts","../src/server.ts"],"sourcesContent":["import type { ChatMessage, ResponsesRequest } from \"../types.js\"\n\nfunction contentToText(content: ChatMessage[\"content\"]): string {\n if (typeof content === \"string\") return content\n\n return content\n .map((part) => part.text ?? part.input_text ?? part.output_text ?? \"\")\n .filter(Boolean)\n .join(\"\\n\")\n}\n\nexport function messagesToPrompt(messages: ChatMessage[]): string {\n const nonEmpty = messages.filter(\n (message) => contentToText(message.content).length > 0,\n )\n\n if (nonEmpty.length === 1 && nonEmpty[0]?.role === \"user\") {\n return contentToText(nonEmpty[0].content)\n }\n\n return nonEmpty\n .map((message) => {\n const label =\n message.role === \"system\"\n ? \"System\"\n : message.role === \"assistant\"\n ? \"Assistant\"\n : \"User\"\n return `[${label}]\\n${contentToText(message.content)}`\n })\n .join(\"\\n\\n\")\n}\n\nfunction responseContentToText(content: unknown): string {\n if (typeof content === \"string\") return content\n if (!Array.isArray(content)) return \"\"\n\n return content\n .map((part) => {\n if (typeof part === \"string\") return part\n if (!part || typeof part !== \"object\") return \"\"\n const record = part as Record<string, unknown>\n return String(\n record.text ?? record.input_text ?? record.output_text ?? \"\",\n )\n })\n .filter(Boolean)\n .join(\"\\n\")\n}\n\nexport function responsesToMessages(request: ResponsesRequest): ChatMessage[] {\n const messages: ChatMessage[] = []\n\n if (request.instructions) {\n messages.push({ role: \"system\", content: request.instructions })\n }\n\n const inputItems = Array.isArray(request.input)\n ? request.input\n : [{ role: \"user\", content: request.input ?? \"\" }]\n\n for (const item of inputItems) {\n if (typeof item === \"string\") {\n messages.push({ role: \"user\", content: item })\n continue\n }\n\n if (!item || typeof item !== \"object\") continue\n const record = item as Record<string, unknown>\n const role =\n record.role === \"assistant\"\n ? \"assistant\"\n : record.role === \"system\"\n ? \"system\"\n : \"user\"\n\n if (record.type === \"message\" || record.role) {\n const text = responseContentToText(record.content)\n if (text) messages.push({ role, content: text })\n continue\n }\n\n if (record.type === \"input_text\" || record.type === \"output_text\") {\n const text = responseContentToText([record])\n if (text) messages.push({ role: \"user\", content: text })\n }\n }\n\n return messages.length > 0 ? messages : [{ role: \"user\", content: \"\" }]\n}\n\nexport function normalizeModel(model: string | undefined): string {\n if (!model) return \"auto\"\n if (model.startsWith(\"cursor/\"))\n return model.slice(\"cursor/\".length) || \"auto\"\n if (model.startsWith(\"cursor-\"))\n return model.slice(\"cursor-\".length) || \"auto\"\n return model\n}\n","import type { BridgeModel } from \"../types.js\"\n\nexport function parseAgentModelList(output: string): BridgeModel[] {\n return output\n .split(\"\\n\")\n .map((line) => line.trim())\n .map((line) => {\n const match = line.match(/^([a-zA-Z0-9_.-]+)\\s+-\\s+(.+)$/)\n return match ? { id: match[1] ?? \"\", name: match[2] ?? \"\" } : null\n })\n .filter((model): model is BridgeModel => Boolean(model?.id && model.name))\n}\n\nexport function toOpenAIModelList(models: BridgeModel[]) {\n const created = Math.floor(Date.now() / 1000)\n return {\n object: \"list\",\n data: models.map((model) => ({\n id: model.id,\n object: \"model\",\n owned_by: \"cursor\",\n created,\n })),\n }\n}\n\nexport function toCodexModelCatalog(models: BridgeModel[]) {\n return {\n models: models.map((model, index) => ({\n slug: model.id,\n display_name: model.name,\n description: \"Cursor model via Cursor Agent CLI.\",\n default_reasoning_level: \"medium\",\n supported_reasoning_levels: [],\n shell_type: \"shell_command\",\n visibility: \"list\",\n supported_in_api: true,\n priority: Math.max(0, 1000 - index),\n additional_speed_tiers: [],\n service_tiers: [],\n default_service_tier: null,\n availability_nux: null,\n upgrade: null,\n base_instructions:\n \"You are Codex, a coding agent. Help the user with software engineering tasks in the current workspace.\",\n model_messages: null,\n supports_reasoning_summaries: false,\n default_reasoning_summary: \"none\",\n support_verbosity: false,\n default_verbosity: \"low\",\n apply_patch_tool_type: \"freeform\",\n web_search_tool_type: \"text_and_image\",\n truncation_policy: { mode: \"tokens\", limit: 10000 },\n supports_parallel_tool_calls: true,\n supports_image_detail_original: true,\n context_window: 128000,\n max_context_window: 128000,\n effective_context_window_percent: 95,\n experimental_supported_tools: [],\n input_modalities: [\"text\"],\n supports_search_tool: false,\n use_responses_lite: false,\n })),\n }\n}\n","import { execFile, spawn } from \"node:child_process\"\nimport { parseAgentModelList } from \"../adapter/models.js\"\nimport type {\n BridgeModel,\n CursorRunEvents,\n CursorRunOptions,\n CursorRunResult,\n} from \"../types.js\"\n\nexport interface CursorRunnerOptions {\n agentPath?: string\n defaultCwd?: string\n timeoutMs?: number\n modelListCacheMs?: number\n maxConcurrentRuns?: number\n yolo?: boolean\n}\n\ntype RunPermit = () => void\nconst defaultMaxConcurrentRuns = 1\nconst forceKillDelayMs = 1_000\n\nexport class CursorRunner {\n readonly agentPath: string\n readonly defaultCwd: string\n readonly timeoutMs: number\n readonly modelListCacheMs: number\n readonly maxConcurrentRuns: number\n readonly yolo: boolean\n private modelCache?: { expiresAt: number; models: BridgeModel[] }\n private activeRuns = 0\n private readonly runQueue: Array<() => void> = []\n private readonly activeChildren = new Set<ReturnType<typeof spawn>>()\n\n constructor(options: CursorRunnerOptions = {}) {\n this.agentPath =\n options.agentPath ?? process.env.CURSOR_AGENT_PATH ?? \"agent\"\n this.defaultCwd = options.defaultCwd ?? process.cwd()\n this.timeoutMs = options.timeoutMs ?? 300_000\n this.modelListCacheMs = options.modelListCacheMs ?? 60_000\n this.maxConcurrentRuns = parsePositiveInteger(\n options.maxConcurrentRuns ??\n Number(\n process.env.CURSOR_AGENT_MAX_CONCURRENT || defaultMaxConcurrentRuns,\n ),\n defaultMaxConcurrentRuns,\n )\n this.yolo = options.yolo ?? process.env.CURSOR_AGENT_YOLO !== \"0\"\n }\n\n async listModels(\n options: { refresh?: boolean } = {},\n ): Promise<BridgeModel[]> {\n const now = Date.now()\n if (\n !options.refresh &&\n this.modelCache &&\n this.modelCache.expiresAt > now\n ) {\n return this.modelCache.models\n }\n\n const models = await new Promise<BridgeModel[]>((resolve, reject) => {\n execFile(\n this.agentPath,\n [\"--list-models\"],\n { timeout: 30_000 },\n (error, stdout) => {\n if (error) {\n reject(error)\n return\n }\n resolve(parseAgentModelList(stdout))\n },\n )\n })\n this.modelCache = { expiresAt: now + this.modelListCacheMs, models }\n return models\n }\n\n async run(\n options: CursorRunOptions,\n events: CursorRunEvents = {},\n ): Promise<CursorRunResult> {\n const release = await this.acquireRunPermit(options.signal)\n try {\n if (options.signal?.aborted) throw new Error(\"Request aborted\")\n return await this.runWithPermit(options, events)\n } finally {\n release()\n }\n }\n\n abortAll() {\n for (const child of this.activeChildren) terminateChild(child)\n }\n\n private acquireRunPermit(signal?: AbortSignal): Promise<RunPermit> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new Error(\"Request aborted\"))\n return\n }\n\n let queuedAcquire: (() => void) | undefined\n const onAbort = () => {\n if (queuedAcquire) {\n this.runQueue.splice(this.runQueue.indexOf(queuedAcquire), 1)\n }\n reject(new Error(\"Request aborted\"))\n }\n const acquire = () => {\n signal?.removeEventListener(\"abort\", onAbort)\n this.activeRuns += 1\n resolve(() => {\n this.activeRuns -= 1\n const next = this.runQueue.shift()\n if (next) next()\n })\n }\n\n if (this.activeRuns < this.maxConcurrentRuns) {\n acquire()\n return\n }\n\n queuedAcquire = acquire\n signal?.addEventListener(\"abort\", onAbort, { once: true })\n this.runQueue.push(acquire)\n })\n }\n\n private runWithPermit(\n options: CursorRunOptions,\n events: CursorRunEvents,\n ): Promise<CursorRunResult> {\n return new Promise((resolve, reject) => {\n const args = [\n \"-p\",\n \"--output-format\",\n \"stream-json\",\n \"--stream-partial-output\",\n ]\n if (this.yolo) args.push(\"--yolo\")\n if (options.model !== \"auto\") args.push(\"--model\", options.model)\n\n const child = spawn(this.agentPath, args, {\n cwd: options.cwd ?? this.defaultCwd,\n env: process.env,\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n })\n this.activeChildren.add(child)\n\n let buffer = \"\"\n let lastModel = options.model\n let lastAssistantText = \"\"\n let finalText: string | undefined\n let stderr = \"\"\n let settled = false\n let forceKillTimer: NodeJS.Timeout | undefined\n\n const timer = setTimeout(() => {\n forceKillTimer = terminateChild(child)\n settle(() =>\n reject(\n new Error(\n `Cursor Agent request timed out after ${this.timeoutMs}ms`,\n ),\n ),\n )\n }, this.timeoutMs)\n\n const onAbort = () => {\n forceKillTimer = terminateChild(child)\n settle(() => reject(new Error(\"Request aborted\")))\n }\n\n const settle = (fn: () => void) => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n if (forceKillTimer && child.exitCode !== null)\n clearTimeout(forceKillTimer)\n options.signal?.removeEventListener(\"abort\", onAbort)\n this.activeChildren.delete(child)\n fn()\n }\n\n options.signal?.addEventListener(\"abort\", onAbort, { once: true })\n\n child.stdin.write(options.prompt)\n child.stdin.end()\n\n child.stdout.on(\"data\", (chunk) => {\n buffer += chunk.toString()\n const lines = buffer.split(\"\\n\")\n buffer = lines.pop() as string\n for (const line of lines) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n const message = JSON.parse(trimmed) as Record<string, unknown>\n if (typeof message.model === \"string\") {\n lastModel = message.model\n events.onModel?.(lastModel)\n }\n\n const text = extractAssistantText(message)\n if (text && text !== lastAssistantText) {\n const delta = text.startsWith(lastAssistantText)\n ? text.slice(lastAssistantText.length)\n : text\n lastAssistantText = text\n events.onDelta?.(delta)\n }\n\n if (typeof message.result === \"string\") finalText = message.result\n } catch {\n // Cursor occasionally emits non-JSON progress lines. They are not protocol data.\n }\n }\n })\n\n child.stderr.on(\"data\", (chunk) => {\n stderr += chunk.toString()\n })\n\n child.on(\"error\", (error) => {\n settle(() => reject(error))\n })\n\n child.on(\"close\", (code) => {\n settle(() => {\n if (code === 0 && (finalText !== undefined || lastAssistantText)) {\n resolve({ text: finalText ?? lastAssistantText, model: lastModel })\n return\n }\n reject(\n new Error(stderr.trim() || `Cursor Agent exited with code ${code}`),\n )\n })\n })\n })\n }\n}\n\nfunction parsePositiveInteger(value: number, fallback: number) {\n return Number.isInteger(value) && value > 0 ? value : fallback\n}\n\nfunction terminateChild(child: ReturnType<typeof spawn>) {\n child.kill(\"SIGTERM\")\n return setTimeout(() => {\n if (child.exitCode === null && child.signalCode === null) {\n child.kill(\"SIGKILL\")\n }\n }, forceKillDelayMs)\n}\n\nfunction extractAssistantText(message: Record<string, unknown>): string {\n const nested = message.message\n if (!nested || typeof nested !== \"object\") return \"\"\n const content = (nested as Record<string, unknown>).content\n if (!Array.isArray(content)) return \"\"\n return content\n .map((part) => {\n if (!part || typeof part !== \"object\") return \"\"\n const record = part as Record<string, unknown>\n return record.type === \"text\" && typeof record.text === \"string\"\n ? record.text\n : \"\"\n })\n .join(\"\")\n}\n","","import { randomUUID } from \"node:crypto\"\n\nexport function createChatResponse(model: string, text: string) {\n return {\n id: `chatcmpl-${randomUUID().replaceAll(\"-\", \"\")}`,\n object: \"chat.completion\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n message: { role: \"assistant\", content: text },\n finish_reason: \"stop\",\n },\n ],\n usage: { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n }\n}\n\nexport function createChatChunk(\n id: string,\n model: string,\n text: string,\n isFirst: boolean,\n) {\n return {\n id,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [\n {\n index: 0,\n delta: { role: isFirst ? \"assistant\" : undefined, content: text },\n finish_reason: null,\n },\n ],\n }\n}\n\nexport function createChatDoneChunk(id: string, model: string) {\n return {\n id,\n object: \"chat.completion.chunk\",\n created: Math.floor(Date.now() / 1000),\n model,\n choices: [{ index: 0, delta: {}, finish_reason: \"stop\" }],\n }\n}\n\nexport function createResponseObject(\n model: string,\n text: string,\n responseId = `resp_${randomUUID().replaceAll(\"-\", \"\")}`,\n itemId = `msg_${randomUUID().replaceAll(\"-\", \"\")}`,\n) {\n const item: {\n id: string\n type: \"message\"\n status: \"completed\"\n role: \"assistant\"\n content: Array<{\n type: \"output_text\"\n text: string\n annotations: unknown[]\n }>\n } = {\n id: itemId,\n type: \"message\",\n status: \"completed\",\n role: \"assistant\",\n content: [{ type: \"output_text\", text, annotations: [] }],\n }\n\n return {\n id: responseId,\n object: \"response\",\n created_at: Math.floor(Date.now() / 1000),\n status: \"completed\",\n model,\n output: [item],\n usage: { input_tokens: 0, output_tokens: 0, total_tokens: 0 },\n }\n}\n\nexport function createResponseStream(model: string) {\n const response = createResponseObject(model, \"\")\n const item = response.output[0]\n /* v8 ignore next -- createResponseObject always creates one output item. */\n if (!item) throw new Error(\"Responses output item was not created\")\n const part = item.content[0]\n /* v8 ignore next -- createResponseObject always creates one output text part. */\n if (!part) throw new Error(\"Responses output text part was not created\")\n\n return {\n response,\n item,\n part,\n events: [\n [\"response.created\", { ...response, status: \"in_progress\", output: [] }],\n [\n \"response.output_item.added\",\n {\n response_id: response.id,\n output_index: 0,\n item: { ...item, status: \"in_progress\", content: [] },\n },\n ],\n [\n \"response.content_part.added\",\n {\n response_id: response.id,\n item_id: item.id,\n output_index: 0,\n content_index: 0,\n part: { ...part, text: \"\" },\n },\n ],\n ] as const,\n }\n}\n\nexport function responseDeltaEvent(\n stream: ReturnType<typeof createResponseStream>,\n delta: string,\n) {\n return [\n \"response.output_text.delta\",\n {\n response_id: stream.response.id,\n item_id: stream.item.id,\n output_index: 0,\n content_index: 0,\n delta,\n },\n ] as const\n}\n\nexport function responseDoneEvents(\n stream: ReturnType<typeof createResponseStream>,\n model: string,\n text: string,\n) {\n const response = createResponseObject(\n model,\n text,\n stream.response.id,\n stream.item.id,\n )\n const item = response.output[0]\n /* v8 ignore next -- createResponseObject always creates one output item. */\n if (!item) throw new Error(\"Responses output item was not created\")\n const part = item.content[0]\n /* v8 ignore next -- createResponseObject always creates one output text part. */\n if (!part) throw new Error(\"Responses output text part was not created\")\n\n return [\n [\n \"response.output_text.done\",\n {\n response_id: response.id,\n item_id: item.id,\n output_index: 0,\n content_index: 0,\n text,\n },\n ],\n [\n \"response.content_part.done\",\n {\n response_id: response.id,\n item_id: item.id,\n output_index: 0,\n content_index: 0,\n part,\n },\n ],\n [\n \"response.output_item.done\",\n { response_id: response.id, output_index: 0, item },\n ],\n [\"response.completed\", { response }],\n ] as const\n}\n\nexport function responseTextEvents(model: string, text: string) {\n const stream = createResponseStream(model)\n return [\n ...stream.events,\n responseDeltaEvent(stream, text),\n ...responseDoneEvents(stream, model, text),\n ] as const\n}\n","import { randomUUID } from \"node:crypto\"\nimport http, { type IncomingMessage, type ServerResponse } from \"node:http\"\nimport packageJson from \"../package.json\" with { type: \"json\" }\nimport {\n messagesToPrompt,\n normalizeModel,\n responsesToMessages,\n} from \"./adapter/messages.js\"\nimport { toCodexModelCatalog, toOpenAIModelList } from \"./adapter/models.js\"\nimport {\n createChatChunk,\n createChatDoneChunk,\n createChatResponse,\n createResponseObject,\n createResponseStream,\n responseDeltaEvent,\n responseDoneEvents,\n} from \"./adapter/openai.js\"\nimport { CursorRunner } from \"./cursor/runner.js\"\nimport type {\n ChatCompletionRequest,\n ResponsesRequest,\n ServerConfig,\n} from \"./types.js\"\n\nconst packageVersion = packageJson.version\nconst defaultMaxBodyBytes = 1024 * 1024\n\nclass RequestError extends Error {\n readonly status: number\n readonly code: string\n\n constructor(status: number, code: string, message: string) {\n super(message)\n this.status = status\n this.code = code\n }\n}\n\nexport async function startServer(config: ServerConfig = {}) {\n const port = config.port ?? Number(process.env.PORT || 4646)\n const host = config.host ?? process.env.HOST ?? \"127.0.0.1\"\n const runner = new CursorRunner({\n ...(config.agentPath ? { agentPath: config.agentPath } : {}),\n ...(config.defaultCwd ? { defaultCwd: config.defaultCwd } : {}),\n })\n const maxBodyBytes = config.maxBodyBytes ?? defaultMaxBodyBytes\n\n const server = http.createServer(async (req, res) => {\n try {\n await route(req, res, runner, maxBodyBytes)\n } catch (error) {\n sendError(res, error)\n }\n })\n server.on(\"close\", () => runner.abortAll())\n\n await new Promise<void>((resolve, reject) => {\n server.listen(port, host, resolve)\n server.once(\"error\", reject)\n })\n\n return server\n}\n\nasync function route(\n req: IncomingMessage,\n res: ServerResponse,\n runner: CursorRunner,\n maxBodyBytes: number,\n) {\n setCors(res)\n const url = new URL(\n req.url ?? \"/\",\n `http://${req.headers.host ?? \"127.0.0.1\"}`,\n )\n\n if (req.method === \"OPTIONS\") {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method === \"GET\" && url.pathname === \"/health\") {\n sendJson(res, 200, {\n status: \"ok\",\n provider: \"cursor-agent-bridge\",\n version: packageVersion,\n })\n return\n }\n\n if (req.method === \"GET\" && url.pathname === \"/v1/models\") {\n const models = await runner.listModels({\n refresh: url.searchParams.get(\"refresh\") === \"1\",\n })\n const wantsCodexCatalog =\n url.searchParams.has(\"client_version\") ||\n url.searchParams.get(\"format\") === \"codex\"\n sendJson(\n res,\n 200,\n wantsCodexCatalog\n ? toCodexModelCatalog(models)\n : toOpenAIModelList(models),\n )\n return\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/chat/completions\") {\n await handleChat(req, res, runner, maxBodyBytes)\n return\n }\n\n if (req.method === \"POST\" && url.pathname === \"/v1/responses\") {\n await handleResponses(req, res, runner, maxBodyBytes)\n return\n }\n\n sendJson(res, 404, {\n error: {\n message: \"Not found\",\n type: \"invalid_request_error\",\n code: \"not_found\",\n },\n })\n}\n\nasync function handleChat(\n req: IncomingMessage,\n res: ServerResponse,\n runner: CursorRunner,\n maxBodyBytes: number,\n) {\n const body = (await readJson(req, maxBodyBytes)) as ChatCompletionRequest\n if (!Array.isArray(body.messages) || body.messages.length === 0) {\n sendJson(res, 400, {\n error: {\n message: \"messages is required and must be a non-empty array\",\n type: \"invalid_request_error\",\n code: \"invalid_messages\",\n },\n })\n return\n }\n\n const model = normalizeModel(body.model)\n const prompt = messagesToPrompt(body.messages)\n const abort = new AbortController()\n req.on(\"close\", () => abort.abort())\n\n if (body.stream === true) {\n const id = `chatcmpl-${randomUUID().replaceAll(\"-\", \"\")}`\n writeSseHeaders(res)\n let isFirst = true\n let lastModel = model\n let streamedText = \"\"\n try {\n const result = await runner.run(\n { model, prompt, signal: abort.signal },\n {\n onDelta: (text) => {\n streamedText += text\n res.write(\n `data: ${JSON.stringify(createChatChunk(id, lastModel, text, isFirst))}\\n\\n`,\n )\n isFirst = false\n },\n onModel: (nextModel) => {\n lastModel = nextModel\n },\n },\n )\n lastModel = result.model\n if (result.text !== streamedText) {\n const delta = result.text.startsWith(streamedText)\n ? result.text.slice(streamedText.length)\n : result.text\n if (delta) {\n res.write(\n `data: ${JSON.stringify(createChatChunk(id, lastModel, delta, isFirst))}\\n\\n`,\n )\n }\n }\n res.write(\n `data: ${JSON.stringify(createChatDoneChunk(id, lastModel))}\\n\\n`,\n )\n res.write(\"data: [DONE]\\n\\n\")\n } catch (error) {\n writeSseError(res, error)\n }\n res.end()\n return\n }\n\n const result = await runner.run({ model, prompt, signal: abort.signal })\n sendJson(res, 200, createChatResponse(result.model, result.text))\n}\n\nasync function handleResponses(\n req: IncomingMessage,\n res: ServerResponse,\n runner: CursorRunner,\n maxBodyBytes: number,\n) {\n const body = (await readJson(req, maxBodyBytes)) as ResponsesRequest\n const model = normalizeModel(body.model)\n const prompt = messagesToPrompt(responsesToMessages(body))\n const abort = new AbortController()\n req.on(\"close\", () => abort.abort())\n\n if (body.stream === false) {\n const result = await runner.run({ model, prompt, signal: abort.signal })\n sendJson(res, 200, createResponseObject(result.model, result.text))\n return\n }\n\n writeSseHeaders(res)\n const stream = createResponseStream(model)\n let lastModel = model\n let streamedText = \"\"\n for (const [event, data] of stream.events) {\n writeSseEvent(res, event, data)\n }\n try {\n const result = await runner.run(\n { model, prompt, signal: abort.signal },\n {\n onDelta: (text) => {\n streamedText += text\n const [event, data] = responseDeltaEvent(stream, text)\n writeSseEvent(res, event, data)\n },\n onModel: (nextModel) => {\n lastModel = nextModel\n },\n },\n )\n lastModel = result.model\n if (result.text !== streamedText) {\n const delta = result.text.startsWith(streamedText)\n ? result.text.slice(streamedText.length)\n : result.text\n if (delta) {\n streamedText += delta\n const [event, data] = responseDeltaEvent(stream, delta)\n writeSseEvent(res, event, data)\n }\n }\n for (const [event, data] of responseDoneEvents(\n stream,\n lastModel,\n result.text,\n )) {\n writeSseEvent(res, event, data)\n }\n } catch (error) {\n writeSseError(res, error)\n }\n res.end()\n}\n\nfunction readJson(\n req: IncomingMessage,\n maxBodyBytes = defaultMaxBodyBytes,\n): Promise<unknown> {\n return new Promise((resolve, reject) => {\n let body = \"\"\n let bytes = 0\n let tooLarge = false\n req.setEncoding(\"utf8\")\n req.on(\"data\", (chunk) => {\n if (tooLarge) return\n bytes += Buffer.byteLength(chunk)\n if (bytes > maxBodyBytes) {\n tooLarge = true\n reject(\n new RequestError(\n 413,\n \"payload_too_large\",\n `Request body exceeds ${maxBodyBytes} bytes`,\n ),\n )\n return\n }\n body += chunk\n })\n req.on(\"end\", () => {\n try {\n resolve(body ? JSON.parse(body) : {})\n } catch {\n reject(new RequestError(400, \"invalid_json\", \"Invalid JSON\"))\n }\n })\n req.on(\"error\", reject)\n })\n}\n\nfunction setCors(res: ServerResponse) {\n res.setHeader(\"Access-Control-Allow-Origin\", \"*\")\n res.setHeader(\"Access-Control-Allow-Methods\", \"GET,POST,OPTIONS\")\n res.setHeader(\"Access-Control-Allow-Headers\", \"Content-Type, Authorization\")\n}\n\nfunction writeSseHeaders(res: ServerResponse) {\n res.writeHead(200, {\n \"content-type\": \"text/event-stream; charset=utf-8\",\n \"cache-control\": \"no-cache\",\n connection: \"keep-alive\",\n })\n}\n\nfunction writeSseEvent(\n res: ServerResponse,\n event: string,\n data: Record<string, unknown>,\n) {\n res.write(`event: ${event}\\n`)\n res.write(`data: ${JSON.stringify({ type: event, ...data })}\\n\\n`)\n}\n\nfunction writeSseError(res: ServerResponse, error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n res.write(\"event: error\\n\")\n res.write(\n `data: ${JSON.stringify({\n type: \"error\",\n error: {\n message,\n type: \"server_error\",\n code: \"internal_error\",\n },\n })}\\n\\n`,\n )\n}\n\nfunction sendError(res: ServerResponse, error: unknown) {\n /* v8 ignore next 4 -- last-resort guard for unexpected errors after SSE headers. */\n if (res.headersSent) {\n writeSseError(res, error)\n res.end()\n return\n }\n const status = error instanceof RequestError ? error.status : 500\n sendJson(res, status, {\n error: {\n message: error instanceof Error ? error.message : String(error),\n type:\n error instanceof RequestError\n ? \"invalid_request_error\"\n : \"server_error\",\n code: error instanceof RequestError ? error.code : \"internal_error\",\n },\n })\n}\n\nfunction sendJson(res: ServerResponse, status: number, value: unknown) {\n /* v8 ignore next -- this is a last-resort guard for errors after SSE headers. */\n if (res.headersSent) return\n const body = JSON.stringify(value)\n res.writeHead(status, {\n \"content-type\": \"application/json; charset=utf-8\",\n \"content-length\": Buffer.byteLength(body),\n })\n res.end(body)\n}\n"],"mappings":"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"}
|