cursor-openai-byok 1.0.2 → 1.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.
@@ -105,9 +105,9 @@ async function sendNdjson(res, iterator) {
105
105
  res.end();
106
106
  }
107
107
 
108
- async function* runCursorAgentLoop(config, payload) {
108
+ async function* runCursorAgentLoop(config, payload, customModels = new Set()) {
109
109
  const requestedModel = payload.model || payload.modelName || payload?.runRequest?.requestedModel?.modelId;
110
- const route = resolveModel(config, requestedModel);
110
+ const route = resolveModel(config, requestedModel, { allowUnconfigured: customModels.has(requestedModel) });
111
111
  const openaiBody = cursorPayloadToOpenAI(payload, route);
112
112
  log("cursor-run", {
113
113
  model: route.model.displayName,
@@ -148,6 +148,7 @@ async function* runCursorAgentLoop(config, payload) {
148
148
  }
149
149
 
150
150
  function createServer() {
151
+ const customModels = new Set();
151
152
  return http.createServer(async (req, res) => {
152
153
  try {
153
154
  if (req.method === "OPTIONS") return sendJson(res, 204, {});
@@ -169,16 +170,25 @@ function createServer() {
169
170
  if (req.method === "GET" && url.pathname === "/cursor/v1/should-handle") {
170
171
  const model = url.searchParams.get("model");
171
172
  try {
172
- const route = resolveModel(config, model);
173
+ const route = resolveModel(config, model, { allowUnconfigured: customModels.has(model) });
173
174
  return sendJson(res, 200, { ok: true, handle: true, model: route.model });
174
175
  } catch {
175
176
  return sendJson(res, 200, { ok: true, handle: false });
176
177
  }
177
178
  }
178
179
 
180
+ if (req.method === "POST" && url.pathname === "/cursor/v1/custom-models") {
181
+ const payload = await readJson(req);
182
+ customModels.clear();
183
+ for (const model of payload.models || []) {
184
+ if (typeof model === "string" && model.length <= 128 && !/[\x00-\x1f\x7f]/.test(model)) customModels.add(model);
185
+ }
186
+ return sendJson(res, 200, { ok: true, models: [...customModels] });
187
+ }
188
+
179
189
  if (req.method === "POST" && url.pathname === "/cursor/v1/run-agent-loop") {
180
190
  const payload = await readJson(req);
181
- return sendNdjson(res, runCursorAgentLoop(config, payload));
191
+ return sendNdjson(res, runCursorAgentLoop(config, payload, customModels));
182
192
  }
183
193
 
184
194
  if (req.method === "POST" && url.pathname === "/cursor/v1/tool-result") {
@@ -350,12 +360,17 @@ function listModels(config) {
350
360
  return models;
351
361
  }
352
362
 
353
- function resolveModel(config, requestedModel) {
363
+ function resolveModel(config, requestedModel, options = {}) {
354
364
  const models = listModels(config);
355
365
  const fallback = config.defaults && config.defaults.model;
356
366
  const target = requestedModel || fallback || (models[0] && models[0].displayName);
357
367
  const found = models.find((m) => m.displayName === target || m.apiModel === target);
358
368
  if (!found) {
369
+ if (options.allowUnconfigured && typeof target === "string" && target) {
370
+ const base = models.find((m) => m.displayName === fallback || m.apiModel === fallback) || models[0];
371
+ const provider = base && config.providers.find((p) => p.id === base.providerId);
372
+ if (provider) return { provider, model: { ...base, displayName: target, apiModel: target } };
373
+ }
359
374
  throw new Error(`Model ${target || "<empty>"} is not configured`);
360
375
  }
361
376
  const provider = config.providers.find((p) => p.id === found.providerId);
@@ -426,6 +441,10 @@ function pidPath() {
426
441
  return path.join(configDir(), "daemon.pid");
427
442
  }
428
443
 
444
+ function watcherPidPath() {
445
+ return path.join(configDir(), "watcher.pid");
446
+ }
447
+
429
448
  function runtimePath(name) {
430
449
  return path.join(configDir(), name);
431
450
  }
@@ -457,6 +476,7 @@ module.exports = {
457
476
  configPath,
458
477
  logPath,
459
478
  pidPath,
479
+ watcherPidPath,
460
480
  runtimePath,
461
481
  platformName,
462
482
  cursorExtensionsDir,
@@ -468,16 +488,15 @@ module.exports = {
468
488
  "package.json": function(module, exports, require, __filename, __dirname) {
469
489
  module.exports = {
470
490
  "name": "cursor-openai-byok",
471
- "version": "1.0.2",
491
+ "version": "1.1.4",
472
492
  "description": "Local BYOK bridge for Cursor using OpenAI-compatible providers.",
473
493
  "displayName": "Cursor OpenAI BYOK",
474
494
  "publisher": "cursor-openai-byok",
475
495
  "type": "commonjs",
496
+ "extensionKind": [
497
+ "ui"
498
+ ],
476
499
  "main": "./lib/extension.js",
477
- "repository": {
478
- "type": "git",
479
- "url": "git+https://git.3weijia.com/base/ai/cursor-openai-byok.git"
480
- },
481
500
  "keywords": [
482
501
  "cursor",
483
502
  "byok",
@@ -501,7 +520,7 @@ module.exports = {
501
520
  "registry": "https://registry.npmjs.org/"
502
521
  },
503
522
  "activationEvents": [
504
- "*"
523
+ "onStartupFinished"
505
524
  ],
506
525
  "contributes": {
507
526
  "commands": [