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 CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  OpenAI-compatible HTTP bridge for the Cursor Agent CLI.
4
4
 
5
- `cursor-agent-bridge` lets Codex and other OpenAI-compatible clients talk to a
6
- local Cursor Agent session at `http://127.0.0.1:4646/v1`. It supports the
7
- Responses API used by Codex custom providers, plus Chat Completions for simpler
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 command is on your `PATH`:
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
- cursor-agent-bridge --version
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
- pnpm exec cursor-agent-bridge serve
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
- cursor-agent-bridge upgrade --check
54
+ cab upgrade --check
47
55
  ```
48
56
 
49
57
  Install the latest published version:
50
58
 
51
59
  ```bash
52
- cursor-agent-bridge upgrade
60
+ cab upgrade
53
61
  ```
54
62
 
55
63
  Options:
56
64
 
57
65
  ```bash
58
- cursor-agent-bridge upgrade --target 0.1.3
59
- cursor-agent-bridge upgrade --manager npm
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
- cursor-agent-bridge launch-agent install
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
- cursor-agent-bridge serve --host 127.0.0.1 --port 4646
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
- cursor-agent-bridge launch-agent install
116
+ cab launch-agent install
109
117
  ```
110
118
 
111
119
  Manage the service:
112
120
 
113
121
  ```bash
114
- cursor-agent-bridge launch-agent status
115
- cursor-agent-bridge launch-agent uninstall
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 `cursor-agent-bridge serve` yourself before starting Codex.
127
+ run `cab serve` yourself before starting Codex.
120
128
 
121
129
  ## Codex Config
122
130
 
123
- Create or update `~/.codex/cursor.config.toml`:
131
+ For Codex CLI profile usage, create or update `~/.codex/cursor.config.toml`:
124
132
 
125
133
  ```bash
126
- cursor-agent-bridge config write
134
+ cab config write
127
135
  ```
128
136
 
129
137
  Preview the generated profile without writing a file:
130
138
 
131
139
  ```bash
132
- cursor-agent-bridge config print
140
+ cab config print
133
141
  ```
134
142
 
135
143
  Validate an existing profile:
136
144
 
137
145
  ```bash
138
- cursor-agent-bridge config check
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
- cursor-agent-bridge doctor
207
+ cab doctor
168
208
  ```
169
209
 
170
210
  List available Cursor models without starting the HTTP server:
171
211
 
172
212
  ```bash
173
- cursor-agent-bridge models
174
- cursor-agent-bridge models --json
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 with `client_version`, the bridge returns the catalog shape
191
- Codex expects for `/model`.
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-Bk7ol2lA.mjs";
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
- return value.replace(/\\(["\\btnfr])/g, (_match, escaped) => ({
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
- })[escaped] ?? escaped);
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-Bk7ol2lA.mjs";
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.4";
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, url.searchParams.has("client_version") || url.searchParams.get("format") === "codex" ? toCodexModelCatalog(models) : toOpenAIModelList(models));
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.4",
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(\"&\", \"&amp;\")\n .replaceAll(\"<\", \"&lt;\")\n .replaceAll(\">\", \"&gt;\")\n .replaceAll('\"', \"&quot;\")\n .replaceAll(\"'\", \"&apos;\")\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":"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"}
@@ -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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"}