cursor-agent-bridge 0.1.2 → 0.1.4

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.
@@ -1,5 +1,4 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
- import { EventEmitter } from "node:events";
3
2
  import { randomUUID } from "node:crypto";
4
3
  import http from "node:http";
5
4
  //#region src/adapter/messages.ts
@@ -136,18 +135,31 @@ function toCodexModelCatalog(models) {
136
135
  }
137
136
  //#endregion
138
137
  //#region src/cursor/runner.ts
139
- var CursorRunner = class extends EventEmitter {
138
+ const defaultMaxConcurrentRuns = 1;
139
+ const forceKillDelayMs = 1e3;
140
+ var CursorRunner = class {
140
141
  agentPath;
141
142
  defaultCwd;
142
143
  timeoutMs;
144
+ modelListCacheMs;
145
+ maxConcurrentRuns;
146
+ yolo;
147
+ modelCache;
148
+ activeRuns = 0;
149
+ runQueue = [];
150
+ activeChildren = /* @__PURE__ */ new Set();
143
151
  constructor(options = {}) {
144
- super();
145
152
  this.agentPath = options.agentPath ?? process.env.CURSOR_AGENT_PATH ?? "agent";
146
153
  this.defaultCwd = options.defaultCwd ?? process.cwd();
147
154
  this.timeoutMs = options.timeoutMs ?? 3e5;
155
+ this.modelListCacheMs = options.modelListCacheMs ?? 6e4;
156
+ this.maxConcurrentRuns = parsePositiveInteger(options.maxConcurrentRuns ?? Number(process.env.CURSOR_AGENT_MAX_CONCURRENT || defaultMaxConcurrentRuns), defaultMaxConcurrentRuns);
157
+ this.yolo = options.yolo ?? process.env.CURSOR_AGENT_YOLO !== "0";
148
158
  }
149
- listModels() {
150
- return new Promise((resolve, reject) => {
159
+ async listModels(options = {}) {
160
+ const now = Date.now();
161
+ if (!options.refresh && this.modelCache && this.modelCache.expiresAt > now) return this.modelCache.models;
162
+ const models = await new Promise((resolve, reject) => {
151
163
  execFile(this.agentPath, ["--list-models"], { timeout: 3e4 }, (error, stdout) => {
152
164
  if (error) {
153
165
  reject(error);
@@ -156,16 +168,62 @@ var CursorRunner = class extends EventEmitter {
156
168
  resolve(parseAgentModelList(stdout));
157
169
  });
158
170
  });
171
+ this.modelCache = {
172
+ expiresAt: now + this.modelListCacheMs,
173
+ models
174
+ };
175
+ return models;
176
+ }
177
+ async run(options, events = {}) {
178
+ const release = await this.acquireRunPermit(options.signal);
179
+ try {
180
+ if (options.signal?.aborted) throw new Error("Request aborted");
181
+ return await this.runWithPermit(options, events);
182
+ } finally {
183
+ release();
184
+ }
185
+ }
186
+ abortAll() {
187
+ for (const child of this.activeChildren) terminateChild(child);
188
+ }
189
+ acquireRunPermit(signal) {
190
+ return new Promise((resolve, reject) => {
191
+ if (signal?.aborted) {
192
+ reject(/* @__PURE__ */ new Error("Request aborted"));
193
+ return;
194
+ }
195
+ let queuedAcquire;
196
+ const onAbort = () => {
197
+ if (queuedAcquire) this.runQueue.splice(this.runQueue.indexOf(queuedAcquire), 1);
198
+ reject(/* @__PURE__ */ new Error("Request aborted"));
199
+ };
200
+ const acquire = () => {
201
+ signal?.removeEventListener("abort", onAbort);
202
+ this.activeRuns += 1;
203
+ resolve(() => {
204
+ this.activeRuns -= 1;
205
+ const next = this.runQueue.shift();
206
+ if (next) next();
207
+ });
208
+ };
209
+ if (this.activeRuns < this.maxConcurrentRuns) {
210
+ acquire();
211
+ return;
212
+ }
213
+ queuedAcquire = acquire;
214
+ signal?.addEventListener("abort", onAbort, { once: true });
215
+ this.runQueue.push(acquire);
216
+ });
159
217
  }
160
- run(options, events = {}) {
218
+ runWithPermit(options, events) {
161
219
  return new Promise((resolve, reject) => {
162
220
  const args = [
163
221
  "-p",
164
222
  "--output-format",
165
223
  "stream-json",
166
- "--stream-partial-output",
167
- "--yolo"
224
+ "--stream-partial-output"
168
225
  ];
226
+ if (this.yolo) args.push("--yolo");
169
227
  if (options.model !== "auto") args.push("--model", options.model);
170
228
  const child = spawn(this.agentPath, args, {
171
229
  cwd: options.cwd ?? this.defaultCwd,
@@ -176,32 +234,38 @@ var CursorRunner = class extends EventEmitter {
176
234
  "pipe"
177
235
  ]
178
236
  });
237
+ this.activeChildren.add(child);
179
238
  let buffer = "";
180
239
  let lastModel = options.model;
181
240
  let lastAssistantText = "";
182
241
  let finalText;
183
242
  let stderr = "";
184
243
  let settled = false;
244
+ let forceKillTimer;
185
245
  const timer = setTimeout(() => {
186
- child.kill("SIGTERM");
187
- reject(/* @__PURE__ */ new Error(`Cursor Agent request timed out after ${this.timeoutMs}ms`));
246
+ forceKillTimer = terminateChild(child);
247
+ settle(() => reject(/* @__PURE__ */ new Error(`Cursor Agent request timed out after ${this.timeoutMs}ms`)));
188
248
  }, this.timeoutMs);
249
+ const onAbort = () => {
250
+ forceKillTimer = terminateChild(child);
251
+ settle(() => reject(/* @__PURE__ */ new Error("Request aborted")));
252
+ };
189
253
  const settle = (fn) => {
190
254
  if (settled) return;
191
255
  settled = true;
192
256
  clearTimeout(timer);
257
+ if (forceKillTimer && child.exitCode !== null) clearTimeout(forceKillTimer);
258
+ options.signal?.removeEventListener("abort", onAbort);
259
+ this.activeChildren.delete(child);
193
260
  fn();
194
261
  };
195
- options.signal?.addEventListener("abort", () => {
196
- child.kill("SIGTERM");
197
- settle(() => reject(/* @__PURE__ */ new Error("Request aborted")));
198
- });
262
+ options.signal?.addEventListener("abort", onAbort, { once: true });
199
263
  child.stdin.write(options.prompt);
200
264
  child.stdin.end();
201
265
  child.stdout.on("data", (chunk) => {
202
266
  buffer += chunk.toString();
203
267
  const lines = buffer.split("\n");
204
- buffer = lines.pop() ?? "";
268
+ buffer = lines.pop();
205
269
  for (const line of lines) {
206
270
  const trimmed = line.trim();
207
271
  if (!trimmed) continue;
@@ -242,6 +306,15 @@ var CursorRunner = class extends EventEmitter {
242
306
  });
243
307
  }
244
308
  };
309
+ function parsePositiveInteger(value, fallback) {
310
+ return Number.isInteger(value) && value > 0 ? value : fallback;
311
+ }
312
+ function terminateChild(child) {
313
+ child.kill("SIGTERM");
314
+ return setTimeout(() => {
315
+ if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
316
+ }, forceKillDelayMs);
317
+ }
245
318
  function extractAssistantText(message) {
246
319
  const nested = message.message;
247
320
  if (!nested || typeof nested !== "object") return "";
@@ -254,6 +327,10 @@ function extractAssistantText(message) {
254
327
  }).join("");
255
328
  }
256
329
  //#endregion
330
+ //#region package.json
331
+ var version = "0.1.4";
332
+ var engines = { "node": ">=22.13" };
333
+ //#endregion
257
334
  //#region src/adapter/openai.ts
258
335
  function createChatResponse(model, text) {
259
336
  return {
@@ -305,9 +382,9 @@ function createChatDoneChunk(id, model) {
305
382
  }]
306
383
  };
307
384
  }
308
- function createResponseObject(model, text, responseId = `resp_${randomUUID().replaceAll("-", "")}`) {
385
+ function createResponseObject(model, text, responseId = `resp_${randomUUID().replaceAll("-", "")}`, itemId = `msg_${randomUUID().replaceAll("-", "")}`) {
309
386
  const item = {
310
- id: `msg_${randomUUID().replaceAll("-", "")}`,
387
+ id: itemId,
311
388
  type: "message",
312
389
  status: "completed",
313
390
  role: "assistant",
@@ -331,46 +408,64 @@ function createResponseObject(model, text, responseId = `resp_${randomUUID().rep
331
408
  }
332
409
  };
333
410
  }
334
- function responseTextEvents(model, text) {
335
- const response = createResponseObject(model, text);
411
+ function createResponseStream(model) {
412
+ const response = createResponseObject(model, "");
336
413
  const item = response.output[0];
337
414
  /* v8 ignore next -- createResponseObject always creates one output item. */
338
415
  if (!item) throw new Error("Responses output item was not created");
339
416
  const part = item.content[0];
340
417
  /* v8 ignore next -- createResponseObject always creates one output text part. */
341
418
  if (!part) throw new Error("Responses output text part was not created");
342
- return [
343
- ["response.created", {
344
- ...response,
345
- status: "in_progress",
346
- output: []
347
- }],
348
- ["response.output_item.added", {
349
- response_id: response.id,
350
- output_index: 0,
351
- item: {
352
- ...item,
419
+ return {
420
+ response,
421
+ item,
422
+ part,
423
+ events: [
424
+ ["response.created", {
425
+ ...response,
353
426
  status: "in_progress",
354
- content: []
355
- }
356
- }],
357
- ["response.content_part.added", {
358
- response_id: response.id,
359
- item_id: item.id,
360
- output_index: 0,
361
- content_index: 0,
362
- part: {
363
- ...part,
364
- text: ""
365
- }
366
- }],
367
- ["response.output_text.delta", {
368
- response_id: response.id,
369
- item_id: item.id,
370
- output_index: 0,
371
- content_index: 0,
372
- delta: text
373
- }],
427
+ output: []
428
+ }],
429
+ ["response.output_item.added", {
430
+ response_id: response.id,
431
+ output_index: 0,
432
+ item: {
433
+ ...item,
434
+ status: "in_progress",
435
+ content: []
436
+ }
437
+ }],
438
+ ["response.content_part.added", {
439
+ response_id: response.id,
440
+ item_id: item.id,
441
+ output_index: 0,
442
+ content_index: 0,
443
+ part: {
444
+ ...part,
445
+ text: ""
446
+ }
447
+ }]
448
+ ]
449
+ };
450
+ }
451
+ function responseDeltaEvent(stream, delta) {
452
+ return ["response.output_text.delta", {
453
+ response_id: stream.response.id,
454
+ item_id: stream.item.id,
455
+ output_index: 0,
456
+ content_index: 0,
457
+ delta
458
+ }];
459
+ }
460
+ function responseDoneEvents(stream, model, text) {
461
+ const response = createResponseObject(model, text, stream.response.id, stream.item.id);
462
+ const item = response.output[0];
463
+ /* v8 ignore next -- createResponseObject always creates one output item. */
464
+ if (!item) throw new Error("Responses output item was not created");
465
+ const part = item.content[0];
466
+ /* v8 ignore next -- createResponseObject always creates one output text part. */
467
+ if (!part) throw new Error("Responses output text part was not created");
468
+ return [
374
469
  ["response.output_text.done", {
375
470
  response_id: response.id,
376
471
  item_id: item.id,
@@ -395,7 +490,17 @@ function responseTextEvents(model, text) {
395
490
  }
396
491
  //#endregion
397
492
  //#region src/server.ts
398
- const packageVersion = "0.1.0";
493
+ const packageVersion = version;
494
+ const defaultMaxBodyBytes = 1024 * 1024;
495
+ var RequestError = class extends Error {
496
+ status;
497
+ code;
498
+ constructor(status, code, message) {
499
+ super(message);
500
+ this.status = status;
501
+ this.code = code;
502
+ }
503
+ };
399
504
  async function startServer(config = {}) {
400
505
  const port = config.port ?? Number(process.env.PORT || 4646);
401
506
  const host = config.host ?? process.env.HOST ?? "127.0.0.1";
@@ -403,24 +508,22 @@ async function startServer(config = {}) {
403
508
  ...config.agentPath ? { agentPath: config.agentPath } : {},
404
509
  ...config.defaultCwd ? { defaultCwd: config.defaultCwd } : {}
405
510
  });
511
+ const maxBodyBytes = config.maxBodyBytes ?? defaultMaxBodyBytes;
406
512
  const server = http.createServer(async (req, res) => {
407
513
  try {
408
- await route(req, res, runner);
514
+ await route(req, res, runner, maxBodyBytes);
409
515
  } catch (error) {
410
- sendJson(res, 500, { error: {
411
- message: error instanceof Error ? error.message : String(error),
412
- type: "server_error",
413
- code: "internal_error"
414
- } });
516
+ sendError(res, error);
415
517
  }
416
518
  });
519
+ server.on("close", () => runner.abortAll());
417
520
  await new Promise((resolve, reject) => {
418
521
  server.listen(port, host, resolve);
419
522
  server.once("error", reject);
420
523
  });
421
524
  return server;
422
525
  }
423
- async function route(req, res, runner) {
526
+ async function route(req, res, runner, maxBodyBytes) {
424
527
  setCors(res);
425
528
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "127.0.0.1"}`);
426
529
  if (req.method === "OPTIONS") {
@@ -437,16 +540,16 @@ async function route(req, res, runner) {
437
540
  return;
438
541
  }
439
542
  if (req.method === "GET" && url.pathname === "/v1/models") {
440
- const models = await runner.listModels();
543
+ const models = await runner.listModels({ refresh: url.searchParams.get("refresh") === "1" });
441
544
  sendJson(res, 200, url.searchParams.has("client_version") || url.searchParams.get("format") === "codex" ? toCodexModelCatalog(models) : toOpenAIModelList(models));
442
545
  return;
443
546
  }
444
547
  if (req.method === "POST" && url.pathname === "/v1/chat/completions") {
445
- await handleChat(req, res, runner);
548
+ await handleChat(req, res, runner, maxBodyBytes);
446
549
  return;
447
550
  }
448
551
  if (req.method === "POST" && url.pathname === "/v1/responses") {
449
- await handleResponses(req, res, runner);
552
+ await handleResponses(req, res, runner, maxBodyBytes);
450
553
  return;
451
554
  }
452
555
  sendJson(res, 404, { error: {
@@ -455,8 +558,8 @@ async function route(req, res, runner) {
455
558
  code: "not_found"
456
559
  } });
457
560
  }
458
- async function handleChat(req, res, runner) {
459
- const body = await readJson(req);
561
+ async function handleChat(req, res, runner, maxBodyBytes) {
562
+ const body = await readJson(req, maxBodyBytes);
460
563
  if (!Array.isArray(body.messages) || body.messages.length === 0) {
461
564
  sendJson(res, 400, { error: {
462
565
  message: "messages is required and must be a non-empty array",
@@ -474,21 +577,32 @@ async function handleChat(req, res, runner) {
474
577
  writeSseHeaders(res);
475
578
  let isFirst = true;
476
579
  let lastModel = model;
477
- await runner.run({
478
- model,
479
- prompt,
480
- signal: abort.signal
481
- }, {
482
- onDelta: (text) => {
483
- res.write(`data: ${JSON.stringify(createChatChunk(id, lastModel, text, isFirst))}\n\n`);
484
- isFirst = false;
485
- },
486
- onModel: (nextModel) => {
487
- lastModel = nextModel;
580
+ let streamedText = "";
581
+ try {
582
+ const result = await runner.run({
583
+ model,
584
+ prompt,
585
+ signal: abort.signal
586
+ }, {
587
+ onDelta: (text) => {
588
+ streamedText += text;
589
+ res.write(`data: ${JSON.stringify(createChatChunk(id, lastModel, text, isFirst))}\n\n`);
590
+ isFirst = false;
591
+ },
592
+ onModel: (nextModel) => {
593
+ lastModel = nextModel;
594
+ }
595
+ });
596
+ lastModel = result.model;
597
+ if (result.text !== streamedText) {
598
+ const delta = result.text.startsWith(streamedText) ? result.text.slice(streamedText.length) : result.text;
599
+ if (delta) res.write(`data: ${JSON.stringify(createChatChunk(id, lastModel, delta, isFirst))}\n\n`);
488
600
  }
489
- });
490
- res.write(`data: ${JSON.stringify(createChatDoneChunk(id, lastModel))}\n\n`);
491
- res.write("data: [DONE]\n\n");
601
+ res.write(`data: ${JSON.stringify(createChatDoneChunk(id, lastModel))}\n\n`);
602
+ res.write("data: [DONE]\n\n");
603
+ } catch (error) {
604
+ writeSseError(res, error);
605
+ }
492
606
  res.end();
493
607
  return;
494
608
  }
@@ -499,43 +613,77 @@ async function handleChat(req, res, runner) {
499
613
  });
500
614
  sendJson(res, 200, createChatResponse(result.model, result.text));
501
615
  }
502
- async function handleResponses(req, res, runner) {
503
- const body = await readJson(req);
616
+ async function handleResponses(req, res, runner, maxBodyBytes) {
617
+ const body = await readJson(req, maxBodyBytes);
504
618
  const model = normalizeModel(body.model);
505
619
  const prompt = messagesToPrompt(responsesToMessages(body));
506
620
  const abort = new AbortController();
507
621
  req.on("close", () => abort.abort());
508
- const result = await runner.run({
509
- model,
510
- prompt,
511
- signal: abort.signal
512
- });
513
622
  if (body.stream === false) {
623
+ const result = await runner.run({
624
+ model,
625
+ prompt,
626
+ signal: abort.signal
627
+ });
514
628
  sendJson(res, 200, createResponseObject(result.model, result.text));
515
629
  return;
516
630
  }
517
631
  writeSseHeaders(res);
518
- for (const [event, data] of responseTextEvents(result.model, result.text)) {
519
- res.write(`event: ${event}\n`);
520
- res.write(`data: ${JSON.stringify({
521
- type: event,
522
- ...data
523
- })}\n\n`);
632
+ const stream = createResponseStream(model);
633
+ let lastModel = model;
634
+ let streamedText = "";
635
+ for (const [event, data] of stream.events) writeSseEvent(res, event, data);
636
+ try {
637
+ const result = await runner.run({
638
+ model,
639
+ prompt,
640
+ signal: abort.signal
641
+ }, {
642
+ onDelta: (text) => {
643
+ streamedText += text;
644
+ const [event, data] = responseDeltaEvent(stream, text);
645
+ writeSseEvent(res, event, data);
646
+ },
647
+ onModel: (nextModel) => {
648
+ lastModel = nextModel;
649
+ }
650
+ });
651
+ lastModel = result.model;
652
+ if (result.text !== streamedText) {
653
+ const delta = result.text.startsWith(streamedText) ? result.text.slice(streamedText.length) : result.text;
654
+ if (delta) {
655
+ streamedText += delta;
656
+ const [event, data] = responseDeltaEvent(stream, delta);
657
+ writeSseEvent(res, event, data);
658
+ }
659
+ }
660
+ for (const [event, data] of responseDoneEvents(stream, lastModel, result.text)) writeSseEvent(res, event, data);
661
+ } catch (error) {
662
+ writeSseError(res, error);
524
663
  }
525
664
  res.end();
526
665
  }
527
- function readJson(req) {
666
+ function readJson(req, maxBodyBytes = defaultMaxBodyBytes) {
528
667
  return new Promise((resolve, reject) => {
529
668
  let body = "";
669
+ let bytes = 0;
670
+ let tooLarge = false;
530
671
  req.setEncoding("utf8");
531
672
  req.on("data", (chunk) => {
673
+ if (tooLarge) return;
674
+ bytes += Buffer.byteLength(chunk);
675
+ if (bytes > maxBodyBytes) {
676
+ tooLarge = true;
677
+ reject(new RequestError(413, "payload_too_large", `Request body exceeds ${maxBodyBytes} bytes`));
678
+ return;
679
+ }
532
680
  body += chunk;
533
681
  });
534
682
  req.on("end", () => {
535
683
  try {
536
684
  resolve(body ? JSON.parse(body) : {});
537
- } catch (error) {
538
- reject(error);
685
+ } catch {
686
+ reject(new RequestError(400, "invalid_json", "Invalid JSON"));
539
687
  }
540
688
  });
541
689
  req.on("error", reject);
@@ -553,6 +701,38 @@ function writeSseHeaders(res) {
553
701
  connection: "keep-alive"
554
702
  });
555
703
  }
704
+ function writeSseEvent(res, event, data) {
705
+ res.write(`event: ${event}\n`);
706
+ res.write(`data: ${JSON.stringify({
707
+ type: event,
708
+ ...data
709
+ })}\n\n`);
710
+ }
711
+ function writeSseError(res, error) {
712
+ const message = error instanceof Error ? error.message : String(error);
713
+ res.write("event: error\n");
714
+ res.write(`data: ${JSON.stringify({
715
+ type: "error",
716
+ error: {
717
+ message,
718
+ type: "server_error",
719
+ code: "internal_error"
720
+ }
721
+ })}\n\n`);
722
+ }
723
+ function sendError(res, error) {
724
+ /* v8 ignore next 4 -- last-resort guard for unexpected errors after SSE headers. */
725
+ if (res.headersSent) {
726
+ writeSseError(res, error);
727
+ res.end();
728
+ return;
729
+ }
730
+ sendJson(res, error instanceof RequestError ? error.status : 500, { error: {
731
+ message: error instanceof Error ? error.message : String(error),
732
+ type: error instanceof RequestError ? "invalid_request_error" : "server_error",
733
+ code: error instanceof RequestError ? error.code : "internal_error"
734
+ } });
735
+ }
556
736
  function sendJson(res, status, value) {
557
737
  /* v8 ignore next -- this is a last-resort guard for errors after SSE headers. */
558
738
  if (res.headersSent) return;
@@ -564,6 +744,6 @@ function sendJson(res, status, value) {
564
744
  res.end(body);
565
745
  }
566
746
  //#endregion
567
- export { toOpenAIModelList as a, responsesToMessages as c, toCodexModelCatalog as i, CursorRunner as n, messagesToPrompt as o, parseAgentModelList as r, normalizeModel as s, startServer as t };
747
+ 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 };
568
748
 
569
- //# sourceMappingURL=server-CuHDT_fJ.mjs.map
749
+ //# sourceMappingURL=server-Bk7ol2lA.mjs.map
@@ -0,0 +1 @@
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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"}