cursorconnect 0.1.5 → 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.
@@ -0,0 +1 @@
1
+ {"cliVersion":"0.1.6","bundledAt":"2026-05-25T09:55:59Z"}
@@ -0,0 +1,2 @@
1
+ /** Версия для relay auth (должна быть ≥ MIN_CLI_VERSION на VPS). */
2
+ export declare function connectorClientVersion(): string;
@@ -0,0 +1,43 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ const MIN_FALLBACK = '0.1.5';
5
+ function readJsonVersion(path) {
6
+ if (!existsSync(path))
7
+ return null;
8
+ try {
9
+ const raw = JSON.parse(readFileSync(path, 'utf-8'));
10
+ const v = raw.cliVersion?.trim() || raw.version?.trim();
11
+ return v || null;
12
+ }
13
+ catch {
14
+ return null;
15
+ }
16
+ }
17
+ /** Версия для relay auth (должна быть ≥ MIN_CLI_VERSION на VPS). */
18
+ export function connectorClientVersion() {
19
+ const fromEnv = process.env.CURSORCONNECT_CLI_VERSION?.trim();
20
+ if (fromEnv && fromEnv !== '0.0.0')
21
+ return fromEnv;
22
+ const bridgeRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
23
+ const fromBundle = readJsonVersion(join(bridgeRoot, 'connector-version.json'));
24
+ if (fromBundle)
25
+ return fromBundle;
26
+ const candidates = [
27
+ join(bridgeRoot, '..', 'connect', 'package.json'),
28
+ join(bridgeRoot, 'package.json'),
29
+ ];
30
+ for (const p of candidates) {
31
+ if (!existsSync(p))
32
+ continue;
33
+ try {
34
+ const pkg = JSON.parse(readFileSync(p, 'utf-8'));
35
+ if (pkg.version?.trim())
36
+ return pkg.version.trim();
37
+ }
38
+ catch {
39
+ /* next */
40
+ }
41
+ }
42
+ return MIN_FALLBACK;
43
+ }
@@ -7,10 +7,13 @@ import { JsonlIndex } from './jsonl-index.js';
7
7
  import { WindowMonitor } from './window-monitor.js';
8
8
  import { Relay } from './relay.js';
9
9
  import { MessageDebugStore } from './message-debug-store.js';
10
+ import { connectorClientVersion } from './connector-client-version.js';
10
11
  async function main() {
11
12
  const config = loadConfig();
12
13
  const selectors = loadSelectors();
14
+ const connectorVersion = connectorClientVersion();
13
15
  console.log('=== CursorConnect Bridge ===');
16
+ console.log(`Connector version: ${connectorVersion} (env=${process.env.CURSORCONNECT_CLI_VERSION?.trim() || '-'})`);
14
17
  console.log(`CDP: ${config.cdpUrl}`);
15
18
  console.log(`Server: http://${config.serverHost}:${config.serverPort}`);
16
19
  if (config.relayUrl) {
@@ -1,4 +1,5 @@
1
1
  import { io } from 'socket.io-client';
2
+ import { connectorClientVersion } from './connector-client-version.js';
2
3
  import { loadPairingIdentity } from './pairing-identity.js';
3
4
  const CLIENT_EVENTS = [
4
5
  'command',
@@ -51,6 +52,8 @@ export class RelayUpstream {
51
52
  role: 'connector',
52
53
  token: this.config.relayToken,
53
54
  roomId: this.config.relayRoomId,
55
+ clientKind: 'connector',
56
+ clientVersion: connectorClientVersion(),
54
57
  },
55
58
  });
56
59
  this.socket.on('connect', () => {
@@ -58,7 +61,12 @@ export class RelayUpstream {
58
61
  this.registerPairing();
59
62
  });
60
63
  this.socket.on('connect_error', (err) => {
61
- console.warn('[relay-upstream] connect_error:', err.message);
64
+ const v = connectorClientVersion();
65
+ console.warn(`[relay-upstream] connect_error: ${err.message} (clientVersion=${v})`);
66
+ if (String(err.message).includes('CLI_VERSION_OUTDATED') ||
67
+ String(err.message).includes('CLI_VERSION_MISSING')) {
68
+ console.warn('[relay-upstream] Обновите cursorconnect: npm install -g cursorconnect@latest && cursorconnect start');
69
+ }
62
70
  });
63
71
  this.socket.on('disconnect', (reason) => {
64
72
  console.log('[relay-upstream] disconnected:', reason);
@@ -243,7 +243,7 @@ export class Relay {
243
243
  const apiKey = this.config.openaiApiKey;
244
244
  if (!apiKey) {
245
245
  res.status(503).json({
246
- error: 'OPENAI_API_KEY not set on bridge (add to bridge/.env)',
246
+ error: 'OPENAI_API_KEY not set on Cursor Connect Mac (add to bridge/.env)',
247
247
  });
248
248
  return;
249
249
  }
@@ -0,0 +1,25 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { resolveBridgeDir } from './bridge-dir.js';
4
+ export function bundledBridgeHasClientVersion() {
5
+ let bridgeDir;
6
+ try {
7
+ bridgeDir = resolveBridgeDir();
8
+ }
9
+ catch {
10
+ return true;
11
+ }
12
+ const relayUpstream = join(bridgeDir, 'dist/relay-upstream.js');
13
+ if (!existsSync(relayUpstream))
14
+ return true;
15
+ return readFileSync(relayUpstream, 'utf8').includes('clientVersion');
16
+ }
17
+ /** npm-пакет должен включать bridge с auth.clientVersion (иначе relay отклоняет connector). */
18
+ export function assertBundledBridgeSupportsRelay() {
19
+ if (bundledBridgeHasClientVersion())
20
+ return;
21
+ console.error('[cursorconnect] Устаревший bridge внутри npm-пакета (нет clientVersion для relay).\n' +
22
+ ' npm install -g cursorconnect@latest\n' +
23
+ ' Если уже latest — дождитесь публикации fix или запускайте из клона: npm run bundle-bridge -w connect');
24
+ process.exit(1);
25
+ }
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { join, resolve } from 'path';
3
3
  import { ensurePairingIdentity, loadPairingIdentity, refreshPairingCode, } from './pairing-identity.js';
4
- import { ensureCursorCdp, isBridgeRunning, startBridge, stopBridge, waitBridgeHealth, waitRelayConnector, } from './launch.js';
4
+ import { ensureCursorCdp, isBridgeRunning, startBridge, stopBridge, waitBridgeHealth, waitRelayPairingReady, } from './launch.js';
5
5
  import { printPairingToTerminal } from './print-pairing.js';
6
6
  import { BRIDGE_LOG_FILE } from './paths.js';
7
7
  import { ensureUserConfig, isValidBridgeDir, resolveBridgeDir, USER_CONFIG_ENV, } from './bridge-dir.js';
@@ -9,6 +9,7 @@ import { configFilePath, saveInstallConfig } from './repo-root.js';
9
9
  import { formatDiagnoseReport, runDiagnose } from './diagnose.js';
10
10
  import { loadEnvFile, resolveRelayConfig } from './relay-config.js';
11
11
  import { ensureCliVersionForRelay } from './version-check.js';
12
+ import { assertBundledBridgeSupportsRelay, bundledBridgeHasClientVersion, } from './bundled-bridge-check.js';
12
13
  import { CLI_VERSION } from './cli-version.js';
13
14
  function bridgeEnv(identity) {
14
15
  ensureUserConfig();
@@ -41,6 +42,7 @@ function startFlags(argv) {
41
42
  };
42
43
  }
43
44
  async function cmdStart(argv) {
45
+ assertBundledBridgeSupportsRelay();
44
46
  const { restartCursor, noRestartCursor } = startFlags(argv);
45
47
  const identity = ensurePairingIdentity();
46
48
  const refreshed = refreshPairingCode(identity);
@@ -65,7 +67,19 @@ async function cmdStart(argv) {
65
67
  if (health.ok && cdpPortOk && !health.cdp) {
66
68
  health = await waitBridgeHealth(15_000, { requireCdp: true });
67
69
  }
68
- await waitRelayConnector(relayUrl, 12_000);
70
+ const pairingReady = await waitRelayPairingReady(relayUrl, refreshed.roomId, 30_000);
71
+ if (!pairingReady.ok) {
72
+ console.error('[cursorconnect] Код не зарегистрирован на relay — приложение его не примет.');
73
+ if (!pairingReady.connectorInRoom) {
74
+ console.error(' Mac не подключён к серверу. Обновите CLI: npm install -g cursorconnect@latest');
75
+ console.error(' Затем снова: cursorconnect start');
76
+ console.error(` Лог bridge: ${BRIDGE_LOG_FILE}`);
77
+ }
78
+ else {
79
+ console.error(' Connector в комнате, но код не на сервере — подождите и повторите start.');
80
+ }
81
+ process.exit(1);
82
+ }
69
83
  if (cdpPortOk && health.ok && !health.cdp) {
70
84
  console.error(`[cursorconnect] CDP не подключён (cdp:false) · лог: ${BRIDGE_LOG_FILE}`);
71
85
  }
@@ -102,7 +116,11 @@ async function cmdStatus() {
102
116
  console.error('Identity не найден — запустите: cursorconnect start');
103
117
  process.exit(1);
104
118
  }
105
- console.error(`[cursorconnect] Cursor Connect работает: ${isBridgeRunning()}`);
119
+ console.log(`CLI: ${CLI_VERSION}`);
120
+ console.log(bundledBridgeHasClientVersion()
121
+ ? 'Bridge bundle: OK (clientVersion в relay-upstream)'
122
+ : 'Bridge bundle: STALE — обновите npm install -g cursorconnect@latest');
123
+ console.log(`Bridge process: ${isBridgeRunning() ? 'running' : 'stopped'}`);
106
124
  printPairingToTerminal(identity);
107
125
  }
108
126
  async function main() {
package/dist/launch.js CHANGED
@@ -121,6 +121,35 @@ export async function waitRelayConnector(relayUrl, maxMs = 45_000) {
121
121
  }
122
122
  return false;
123
123
  }
124
+ /** Mac в relay-комнате и pairing-код зарегистрирован (иначе app получит 404). */
125
+ export async function waitRelayPairingReady(relayUrl, roomId, maxMs = 45_000) {
126
+ const base = relayUrl.replace(/\/$/, '');
127
+ const deadline = Date.now() + maxMs;
128
+ let lastConnector = false;
129
+ let lastCodes = 0;
130
+ while (Date.now() < deadline) {
131
+ try {
132
+ const res = await fetch(`${base}/api/diagnostics?roomId=${encodeURIComponent(roomId)}`, { signal: AbortSignal.timeout(8_000) });
133
+ if (res.ok) {
134
+ const d = (await res.json());
135
+ lastConnector = Boolean(d.connectorInRoom);
136
+ lastCodes = d.pairingCodesActive ?? 0;
137
+ if (lastConnector && lastCodes > 0) {
138
+ return { ok: true, connectorInRoom: true, pairingCodesActive: lastCodes };
139
+ }
140
+ }
141
+ }
142
+ catch {
143
+ /* retry */
144
+ }
145
+ await sleep(800);
146
+ }
147
+ return {
148
+ ok: false,
149
+ connectorInRoom: lastConnector,
150
+ pairingCodesActive: lastCodes,
151
+ };
152
+ }
124
153
  export function isCursorRunning() {
125
154
  try {
126
155
  execSync('pgrep -x Cursor', { stdio: 'ignore' });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursorconnect",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "CLI: Cursor Connect on Mac + relay pairing — install once, run from anywhere",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "minCliVersion": "0.1.4",
3
3
  "minAppVersion": "0.2.2",
4
- "latestCliVersion": "0.1.4",
4
+ "latestCliVersion": "0.1.6",
5
5
  "latestAppVersion": "0.2.2",
6
6
  "updateCliCommand": "npm install -g cursorconnect@latest",
7
7
  "updateAppHint": "Обновите CursorConnect в App Store / TestFlight до последней сборки."