claude-overnight 1.19.1 → 1.23.1
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/dist/_version.d.ts +1 -1
- package/dist/_version.js +1 -1
- package/dist/providers.d.ts +10 -10
- package/dist/providers.js +119 -155
- package/package.json +2 -1
- package/plugins/claude-overnight/.claude-plugin/plugin.json +1 -1
package/dist/_version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "1.
|
|
1
|
+
export declare const VERSION = "1.23.1";
|
package/dist/_version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by build — do not edit manually.
|
|
2
|
-
export const VERSION = "1.
|
|
2
|
+
export const VERSION = "1.23.1";
|
package/dist/providers.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export declare const PROXY_DEFAULT_URL = "http://127.0.0.1:8765";
|
|
|
58
58
|
export declare function isCursorProxyProvider(p: ProviderConfig): boolean;
|
|
59
59
|
/**
|
|
60
60
|
* Health check: GET /health on the proxy. Returns true if proxy is reachable.
|
|
61
|
+
* Passes the stored API key so the /health endpoint doesn't return 401.
|
|
61
62
|
*/
|
|
62
63
|
export declare function healthCheckCursorProxy(baseUrl?: string): Promise<boolean>;
|
|
63
64
|
/**
|
|
@@ -68,22 +69,21 @@ export declare function fetchCursorModels(baseUrl?: string): Promise<string[]>;
|
|
|
68
69
|
/**
|
|
69
70
|
* Auto-start the cursor-api-proxy as a detached background process.
|
|
70
71
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* segfaults with --list-models on macOS (exit 139), so we resolve the
|
|
74
|
-
* system `node` binary and the agent's index.js, patch the proxy's env.js
|
|
75
|
-
* to respect CURSOR_AGENT_NODE/SCRIPT on Unix, and pass those env vars.
|
|
72
|
+
* Passes CURSOR_AGENT_NODE/SCRIPT so the fork uses system Node.js for the
|
|
73
|
+
* agent subprocess (avoids segfaults with --list-models on macOS).
|
|
76
74
|
*
|
|
77
75
|
* Handles:
|
|
78
76
|
* - Proxy already running and verified → returns true immediately
|
|
79
|
-
* - Something on the port but not our proxy → warns,
|
|
80
|
-
* -
|
|
81
|
-
* -
|
|
82
|
-
*
|
|
77
|
+
* - Something on the port but not our proxy → warns, kills, restarts
|
|
78
|
+
* - Proxy not running → spawns detached, waits for health
|
|
79
|
+
* - Spawn fails → returns false, caller falls back to manual instructions
|
|
80
|
+
*
|
|
81
|
+
* When `forceRestart` is true and a stale process is on the port, it will be
|
|
82
|
+
* killed and the proxy restarted.
|
|
83
83
|
*
|
|
84
84
|
* Returns true when the proxy is reachable at PROXY_DEFAULT_URL.
|
|
85
85
|
*/
|
|
86
|
-
export declare function ensureCursorProxyRunning(baseUrl?: string): Promise<boolean>;
|
|
86
|
+
export declare function ensureCursorProxyRunning(baseUrl?: string, forceRestart?: boolean): Promise<boolean>;
|
|
87
87
|
/**
|
|
88
88
|
* Full install + configure flow for cursor-api-proxy.
|
|
89
89
|
* Walks through CLI install, API key config, and proxy start.
|
package/dist/providers.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, realpathSync
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, chmodSync, realpathSync } from "fs";
|
|
2
2
|
import { homedir } from "os";
|
|
3
3
|
import { join, dirname } from "path";
|
|
4
4
|
import { execSync, spawn } from "child_process";
|
|
@@ -262,13 +262,28 @@ export const PROXY_DEFAULT_URL = "http://127.0.0.1:8765";
|
|
|
262
262
|
export function isCursorProxyProvider(p) {
|
|
263
263
|
return p.cursorProxy === true || p.baseURL === PROXY_DEFAULT_URL;
|
|
264
264
|
}
|
|
265
|
+
/** Resolve the cursor-api-proxy API key from env or providers.json. */
|
|
266
|
+
function resolveCursorProxyKey() {
|
|
267
|
+
if (process.env.CURSOR_BRIDGE_API_KEY?.trim())
|
|
268
|
+
return process.env.CURSOR_BRIDGE_API_KEY.trim();
|
|
269
|
+
const saved = loadProviders().find(p => p.cursorProxy);
|
|
270
|
+
if (saved?.cursorApiKey?.trim())
|
|
271
|
+
return saved.cursorApiKey.trim();
|
|
272
|
+
return null;
|
|
273
|
+
}
|
|
274
|
+
/** Build fetch options with the cursor proxy auth header if a key is available. */
|
|
275
|
+
function cursorProxyFetchOpts() {
|
|
276
|
+
const key = resolveCursorProxyKey();
|
|
277
|
+
return key ? { headers: { Authorization: `Bearer ${key}` } } : {};
|
|
278
|
+
}
|
|
265
279
|
/**
|
|
266
280
|
* Health check: GET /health on the proxy. Returns true if proxy is reachable.
|
|
281
|
+
* Passes the stored API key so the /health endpoint doesn't return 401.
|
|
267
282
|
*/
|
|
268
283
|
export async function healthCheckCursorProxy(baseUrl = PROXY_DEFAULT_URL) {
|
|
269
284
|
const url = `${baseUrl.replace(/\/$/, "")}/health`;
|
|
270
285
|
try {
|
|
271
|
-
const res = await fetch(url, { method: "GET", signal: AbortSignal.timeout(3_000) });
|
|
286
|
+
const res = await fetch(url, { method: "GET", signal: AbortSignal.timeout(3_000), ...cursorProxyFetchOpts() });
|
|
272
287
|
return res.ok;
|
|
273
288
|
}
|
|
274
289
|
catch {
|
|
@@ -282,7 +297,7 @@ export async function healthCheckCursorProxy(baseUrl = PROXY_DEFAULT_URL) {
|
|
|
282
297
|
export async function fetchCursorModels(baseUrl = PROXY_DEFAULT_URL) {
|
|
283
298
|
const url = `${baseUrl.replace(/\/$/, "")}/v1/models`;
|
|
284
299
|
try {
|
|
285
|
-
const res = await fetch(url, { method: "GET", signal: AbortSignal.timeout(5_000) });
|
|
300
|
+
const res = await fetch(url, { method: "GET", signal: AbortSignal.timeout(5_000), ...cursorProxyFetchOpts() });
|
|
286
301
|
if (!res.ok)
|
|
287
302
|
return [];
|
|
288
303
|
const json = await res.json();
|
|
@@ -336,16 +351,26 @@ async function fetchLiveCursorModels() {
|
|
|
336
351
|
}
|
|
337
352
|
/**
|
|
338
353
|
* Verify something is actually cursor-api-proxy (not just any HTTP service on the port).
|
|
339
|
-
*
|
|
354
|
+
* Tries /health first (proxy identity), then falls back to /v1/models shape check.
|
|
355
|
+
* Returns true if it looks like the proxy.
|
|
340
356
|
*/
|
|
341
357
|
async function verifyCursorProxy(baseUrl = PROXY_DEFAULT_URL) {
|
|
342
|
-
const url =
|
|
358
|
+
const url = baseUrl.replace(/\/$/, "");
|
|
359
|
+
const opts = cursorProxyFetchOpts();
|
|
360
|
+
// /health is the most reliable proxy identity check — works even when
|
|
361
|
+
// /v1/models fails due to agent subprocess crash (macOS segfault).
|
|
343
362
|
try {
|
|
344
|
-
const res = await fetch(url
|
|
363
|
+
const res = await fetch(`${url}/health`, { method: "GET", signal: AbortSignal.timeout(3_000), ...opts });
|
|
364
|
+
if (res.ok)
|
|
365
|
+
return true;
|
|
366
|
+
}
|
|
367
|
+
catch { }
|
|
368
|
+
// Fallback: check /v1/models response shape
|
|
369
|
+
try {
|
|
370
|
+
const res = await fetch(`${url}/v1/models`, { method: "GET", signal: AbortSignal.timeout(3_000), ...opts });
|
|
345
371
|
if (!res.ok)
|
|
346
372
|
return false;
|
|
347
373
|
const json = await res.json();
|
|
348
|
-
// cursor-api-proxy returns { data: [{ id: "...", ... }] }
|
|
349
374
|
return Array.isArray(json?.data);
|
|
350
375
|
}
|
|
351
376
|
catch {
|
|
@@ -353,143 +378,65 @@ async function verifyCursorProxy(baseUrl = PROXY_DEFAULT_URL) {
|
|
|
353
378
|
}
|
|
354
379
|
}
|
|
355
380
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
|
|
359
|
-
async function isPortInUse(port, host = "127.0.0.1") {
|
|
360
|
-
try {
|
|
361
|
-
const res = await fetch(`http://${host}:${port}/health`, {
|
|
362
|
-
method: "GET",
|
|
363
|
-
signal: AbortSignal.timeout(2_000),
|
|
364
|
-
});
|
|
365
|
-
return res.ok || res.status >= 400; // any response means something is listening
|
|
366
|
-
}
|
|
367
|
-
catch {
|
|
368
|
-
return false;
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
/**
|
|
372
|
-
* Find the system `node` binary path. Uses `which` to bypass any bundled node.
|
|
381
|
+
* Kill whatever process is bound to the given port. Uses `lsof` on macOS /
|
|
382
|
+
* `fuser` on Linux. Returns the PID that was killed, or null if nothing found
|
|
383
|
+
* or permission denied.
|
|
373
384
|
*/
|
|
374
|
-
function
|
|
385
|
+
function killProcessOnPort(port, host = "127.0.0.1") {
|
|
375
386
|
try {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
387
|
+
// macOS / BSD: lsof -ti :PORT gives just the PID
|
|
388
|
+
const pid = execSync(`lsof -ti :${port} 2>/dev/null`, {
|
|
389
|
+
timeout: 5_000, encoding: "utf-8",
|
|
390
|
+
}).trim().split("\n")[0];
|
|
391
|
+
if (!pid || !/^\d+$/.test(pid))
|
|
392
|
+
return null;
|
|
393
|
+
execSync(`kill -9 ${pid} 2>/dev/null`, { timeout: 5_000 });
|
|
394
|
+
return parseInt(pid, 10);
|
|
379
395
|
}
|
|
380
396
|
catch {
|
|
381
397
|
return null;
|
|
382
398
|
}
|
|
383
399
|
}
|
|
384
400
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
401
|
+
* Check whether something is already listening on the proxy port.
|
|
402
|
+
* Returns true if any process bound the port (another instance, Cursor CLI, etc.).
|
|
387
403
|
*/
|
|
388
|
-
function
|
|
404
|
+
async function isPortInUse(port, host = "127.0.0.1") {
|
|
389
405
|
try {
|
|
390
|
-
const
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
const dir = dirname(realpathSync(agentPath));
|
|
396
|
-
const indexPath = `${dir}/index.js`;
|
|
397
|
-
return existsSync(indexPath) ? indexPath : null;
|
|
406
|
+
const res = await fetch(`http://${host}:${port}/health`, {
|
|
407
|
+
method: "GET",
|
|
408
|
+
signal: AbortSignal.timeout(2_000),
|
|
409
|
+
});
|
|
410
|
+
return res.ok || res.status >= 400; // any response means something is listening
|
|
398
411
|
}
|
|
399
412
|
catch {
|
|
400
|
-
return null;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
/**
|
|
404
|
-
* Patch the proxy's env.js to use CURSOR_AGENT_NODE + CURSOR_AGENT_SCRIPT on Unix.
|
|
405
|
-
*
|
|
406
|
-
* The proxy already reads these env vars (lines 152-153 of env.js) but only uses
|
|
407
|
-
* them on Windows in resolveAgentCommand(). We inject a Unix code path before the
|
|
408
|
-
* final `return { command: cmd, args, env }` so that when these vars are set,
|
|
409
|
-
* the proxy spawns system node with the agent script instead of the bundled node
|
|
410
|
-
* (which segfaults with --list-models on macOS).
|
|
411
|
-
*
|
|
412
|
-
* Safe to call repeatedly — the patch is idempotent.
|
|
413
|
-
*/
|
|
414
|
-
function patchProxyEnvJs(proxyDir) {
|
|
415
|
-
const envJs = join(proxyDir, "dist", "lib", "env.js");
|
|
416
|
-
if (!existsSync(envJs))
|
|
417
413
|
return false;
|
|
418
|
-
const src = readFileSync(envJs, "utf-8");
|
|
419
|
-
// Check if already patched
|
|
420
|
-
if (src.includes("/* claude-overnight patch */"))
|
|
421
|
-
return true;
|
|
422
|
-
const patch = `\n/* claude-overnight patch: use CURSOR_AGENT_NODE+SCRIPT on unix */\n` +
|
|
423
|
-
`if (platform !== "win32" && loaded.agentNode && loaded.agentScript) {\n` +
|
|
424
|
-
` return { command: loaded.agentNode, args: [loaded.agentScript, ...args], env: { ...env, CURSOR_INVOKED_AS: "agent" }, agentScriptPath: loaded.agentScript };\n` +
|
|
425
|
-
`}`;
|
|
426
|
-
// Insert before the final return in resolveAgentCommand
|
|
427
|
-
const target = " return { command: cmd, args, env };\n}";
|
|
428
|
-
if (!src.includes(target)) {
|
|
429
|
-
// Try minified variant
|
|
430
|
-
const target2 = "return{command:cmd,args,env}}";
|
|
431
|
-
if (!src.includes(target2))
|
|
432
|
-
return false;
|
|
433
|
-
writeFileSync(envJs, src.replace(target2, patch + "\n" + target2), "utf-8");
|
|
434
|
-
}
|
|
435
|
-
else {
|
|
436
|
-
writeFileSync(envJs, src.replace(target, patch + "\n" + target), "utf-8");
|
|
437
|
-
}
|
|
438
|
-
return true;
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Find the cursor-api-proxy package directory (npx cache or global install).
|
|
442
|
-
*/
|
|
443
|
-
function findProxyPackageDir() {
|
|
444
|
-
try {
|
|
445
|
-
// Try npx cache first
|
|
446
|
-
const npmCacheRoot = join(homedir(), ".npm", "_npx");
|
|
447
|
-
if (existsSync(npmCacheRoot)) {
|
|
448
|
-
const dirs = readdirSync(npmCacheRoot);
|
|
449
|
-
for (const d of dirs) {
|
|
450
|
-
const candidate = join(npmCacheRoot, d, "node_modules", "cursor-api-proxy");
|
|
451
|
-
if (existsSync(join(candidate, "dist", "lib", "env.js")))
|
|
452
|
-
return candidate;
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
414
|
}
|
|
456
|
-
catch { }
|
|
457
|
-
// Try global install
|
|
458
|
-
try {
|
|
459
|
-
const globalDir = execSync("npm root -g 2>/dev/null", {
|
|
460
|
-
timeout: 5_000, encoding: "utf-8", shell: "bash",
|
|
461
|
-
}).trim();
|
|
462
|
-
if (globalDir && existsSync(join(globalDir, "cursor-api-proxy", "dist", "lib", "env.js"))) {
|
|
463
|
-
return join(globalDir, "cursor-api-proxy");
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
catch { }
|
|
467
|
-
return null;
|
|
468
415
|
}
|
|
469
416
|
/**
|
|
470
417
|
* Auto-start the cursor-api-proxy as a detached background process.
|
|
471
418
|
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
* segfaults with --list-models on macOS (exit 139), so we resolve the
|
|
475
|
-
* system `node` binary and the agent's index.js, patch the proxy's env.js
|
|
476
|
-
* to respect CURSOR_AGENT_NODE/SCRIPT on Unix, and pass those env vars.
|
|
419
|
+
* Passes CURSOR_AGENT_NODE/SCRIPT so the fork uses system Node.js for the
|
|
420
|
+
* agent subprocess (avoids segfaults with --list-models on macOS).
|
|
477
421
|
*
|
|
478
422
|
* Handles:
|
|
479
423
|
* - Proxy already running and verified → returns true immediately
|
|
480
|
-
* - Something on the port but not our proxy → warns,
|
|
481
|
-
* -
|
|
482
|
-
* -
|
|
483
|
-
*
|
|
424
|
+
* - Something on the port but not our proxy → warns, kills, restarts
|
|
425
|
+
* - Proxy not running → spawns detached, waits for health
|
|
426
|
+
* - Spawn fails → returns false, caller falls back to manual instructions
|
|
427
|
+
*
|
|
428
|
+
* When `forceRestart` is true and a stale process is on the port, it will be
|
|
429
|
+
* killed and the proxy restarted.
|
|
484
430
|
*
|
|
485
431
|
* Returns true when the proxy is reachable at PROXY_DEFAULT_URL.
|
|
486
432
|
*/
|
|
487
|
-
export async function ensureCursorProxyRunning(baseUrl = PROXY_DEFAULT_URL) {
|
|
433
|
+
export async function ensureCursorProxyRunning(baseUrl = PROXY_DEFAULT_URL, forceRestart = false) {
|
|
488
434
|
const url = new URL(baseUrl);
|
|
489
435
|
const port = parseInt(url.port, 10) || 80;
|
|
490
436
|
// Already healthy?
|
|
491
|
-
if (await healthCheckCursorProxy(baseUrl))
|
|
437
|
+
if (await healthCheckCursorProxy(baseUrl)) {
|
|
492
438
|
return true;
|
|
439
|
+
}
|
|
493
440
|
// Something bound the port — verify it's actually the cursor proxy
|
|
494
441
|
if (await isPortInUse(port, url.hostname)) {
|
|
495
442
|
const isProxy = await verifyCursorProxy(baseUrl);
|
|
@@ -497,38 +444,53 @@ export async function ensureCursorProxyRunning(baseUrl = PROXY_DEFAULT_URL) {
|
|
|
497
444
|
console.log(chalk.dim(` Proxy verified at port ${port}`));
|
|
498
445
|
return true;
|
|
499
446
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
447
|
+
// Stale process on the port — kill it if forceRestart, or try automatically
|
|
448
|
+
if (!forceRestart) {
|
|
449
|
+
console.log(chalk.yellow(` ⚠ Something is on port ${port} but it's not cursor-api-proxy — killing stale process…`));
|
|
450
|
+
}
|
|
451
|
+
const killedPid = killProcessOnPort(port, url.hostname);
|
|
452
|
+
if (killedPid) {
|
|
453
|
+
console.log(chalk.green(` ✓ Killed stale process PID ${killedPid} on port ${port}`));
|
|
454
|
+
await new Promise(r => setTimeout(r, 500));
|
|
455
|
+
return startProxyProcess(baseUrl, url, port);
|
|
456
|
+
}
|
|
457
|
+
// Couldn't kill (permission denied, already gone) — try starting anyway
|
|
458
|
+
console.log(chalk.yellow(` ⚠ Couldn't kill process on port ${port} — attempting to start proxy anyway…`));
|
|
459
|
+
return startProxyProcess(baseUrl, url, port);
|
|
503
460
|
}
|
|
504
461
|
// Port is free — auto-start the proxy
|
|
462
|
+
return startProxyProcess(baseUrl, url, port);
|
|
463
|
+
}
|
|
464
|
+
/** Spawn the proxy process and wait for it to become healthy. */
|
|
465
|
+
async function startProxyProcess(baseUrl, url, port) {
|
|
505
466
|
console.log(chalk.yellow(`\n Proxy not running at ${baseUrl} — starting it for you…`));
|
|
506
|
-
// Resolve system node and agent index.js so the proxy
|
|
507
|
-
// agent
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
}
|
|
467
|
+
// Resolve system node and agent index.js so the proxy uses system Node.js
|
|
468
|
+
// for the agent subprocess (avoids segfaults with --list-models on macOS).
|
|
469
|
+
let sysNode = null;
|
|
470
|
+
let agentJs = null;
|
|
471
|
+
try {
|
|
472
|
+
sysNode = execSync("which node 2>/dev/null", { timeout: 3_000, encoding: "utf-8", shell: "bash" }).trim() || null;
|
|
473
|
+
const agentPath = execSync("command -v agent 2>/dev/null || command -v cursor-agent 2>/dev/null", {
|
|
474
|
+
timeout: 3_000, encoding: "utf-8", shell: "bash",
|
|
475
|
+
}).trim();
|
|
476
|
+
if (agentPath) {
|
|
477
|
+
const agentDir = dirname(realpathSync(agentPath));
|
|
478
|
+
const indexPath = `${agentDir}/index.js`;
|
|
479
|
+
if (existsSync(indexPath))
|
|
480
|
+
agentJs = indexPath;
|
|
521
481
|
}
|
|
522
482
|
}
|
|
483
|
+
catch { }
|
|
523
484
|
const proxyEnv = {
|
|
524
485
|
...Object.fromEntries(Object.entries(process.env).filter(([, v]) => v !== undefined)),
|
|
525
486
|
CURSOR_BRIDGE_API_KEY: process.env.CURSOR_BRIDGE_API_KEY
|
|
526
487
|
|| loadProviders().find(p => p.cursorProxy)?.cursorApiKey
|
|
527
488
|
|| "unused",
|
|
528
489
|
};
|
|
529
|
-
if (
|
|
490
|
+
if (sysNode && agentJs) {
|
|
530
491
|
proxyEnv.CURSOR_AGENT_NODE = sysNode;
|
|
531
492
|
proxyEnv.CURSOR_AGENT_SCRIPT = agentJs;
|
|
493
|
+
console.log(chalk.dim(` Using system node for agent subprocess: ${sysNode}`));
|
|
532
494
|
}
|
|
533
495
|
try {
|
|
534
496
|
const child = spawn("npx", ["cursor-api-proxy"], {
|
|
@@ -746,11 +708,11 @@ export async function setupCursorProxy() {
|
|
|
746
708
|
console.log(chalk.white(` ${chalk.bold("npx cursor-api-proxy")}`));
|
|
747
709
|
for (;;) {
|
|
748
710
|
const choice = await selectKey(` Proxy started?`, [
|
|
749
|
-
{ key: "r", desc: "etry" },
|
|
711
|
+
{ key: "r", desc: "etry (re-attempt auto-start + kill stale)" },
|
|
750
712
|
{ key: "c", desc: "ancel" },
|
|
751
713
|
]);
|
|
752
714
|
if (choice === "r") {
|
|
753
|
-
if (await
|
|
715
|
+
if (await ensureCursorProxyRunning(PROXY_DEFAULT_URL, true)) {
|
|
754
716
|
console.log(chalk.green("\n ✓ Proxy is running and healthy"));
|
|
755
717
|
return true;
|
|
756
718
|
}
|
|
@@ -802,36 +764,38 @@ async function pickCursorModel() {
|
|
|
802
764
|
clearInterval(spinner);
|
|
803
765
|
process.stdout.write("\x1B[2K\r");
|
|
804
766
|
if (!healthy) {
|
|
805
|
-
// Try to auto-start the proxy
|
|
767
|
+
// Try to auto-start the proxy (auto-kills stale processes)
|
|
806
768
|
const autoStarted = await ensureCursorProxyRunning();
|
|
807
769
|
if (autoStarted) {
|
|
808
770
|
// Proxy is up now — proceed to model list
|
|
809
771
|
}
|
|
810
772
|
else {
|
|
811
773
|
console.log(chalk.yellow(" Proxy is not running at " + PROXY_DEFAULT_URL));
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
774
|
+
for (;;) {
|
|
775
|
+
const choice = await selectKey(` How to proceed?`, [
|
|
776
|
+
{ key: "r", desc: "etry (re-attempt auto-start + kill stale)" },
|
|
777
|
+
{ key: "i", desc: "nstall + configure (CLI, API key, server)" },
|
|
778
|
+
{ key: "c", desc: "ancel" },
|
|
779
|
+
]);
|
|
780
|
+
if (choice === "r") {
|
|
781
|
+
if (await ensureCursorProxyRunning(PROXY_DEFAULT_URL, true)) {
|
|
782
|
+
console.log(chalk.green(" ✓ Proxy started"));
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
console.log(chalk.yellow(` Still not reachable at ${PROXY_DEFAULT_URL}`));
|
|
786
|
+
}
|
|
787
|
+
else if (choice === "i") {
|
|
788
|
+
const ok = await setupCursorProxy();
|
|
789
|
+
if (!ok)
|
|
790
|
+
return null;
|
|
791
|
+
if (await healthCheckCursorProxy())
|
|
792
|
+
break;
|
|
820
793
|
return null;
|
|
821
|
-
}
|
|
822
|
-
else if (choice === "r") {
|
|
823
|
-
// User manually started it — one more health check
|
|
824
|
-
if (await healthCheckCursorProxy()) {
|
|
825
|
-
console.log(chalk.green(" ✓ Proxy detected"));
|
|
826
794
|
}
|
|
827
795
|
else {
|
|
828
|
-
console.log(chalk.yellow(" Still not reachable — try the install flow or cancel."));
|
|
829
796
|
return null;
|
|
830
797
|
}
|
|
831
798
|
}
|
|
832
|
-
else {
|
|
833
|
-
return null;
|
|
834
|
-
}
|
|
835
799
|
}
|
|
836
800
|
}
|
|
837
801
|
const { top, more } = await buildCursorPicker();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-overnight",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.1",
|
|
4
4
|
"description": "Background lane for your Claude Max plan. Parallel Claude Agent SDK sessions in git worktrees with a usage cap that reserves headroom for your interactive Claude Code. Crash-safe resume. Provider-agnostic model catalog with capability-based planning.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@anthropic-ai/claude-agent-sdk": "^0.2.92",
|
|
18
|
+
"@claude-overnight/cursor-api-proxy": "file:../cursor-api-proxy",
|
|
18
19
|
"chalk": "^5.4.1",
|
|
19
20
|
"jsonwebtoken": "^9.0.2"
|
|
20
21
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-overnight",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.1",
|
|
4
4
|
"description": "Claude Code skill for understanding, installing, and inspecting claude-overnight runs -- parallel Claude agents in git worktrees with thinking waves, multi-wave steering, and crash-safe resume. Supports Cursor API Proxy, Qwen, OpenRouter.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Francesco Fornace"
|