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.
- package/bridge-runtime/connector-version.json +1 -0
- package/bridge-runtime/dist/connector-client-version.d.ts +2 -0
- package/bridge-runtime/dist/connector-client-version.js +43 -0
- package/bridge-runtime/dist/index.js +3 -0
- package/bridge-runtime/dist/relay-upstream.js +9 -1
- package/bridge-runtime/dist/relay.js +1 -1
- package/dist/bundled-bridge-check.js +25 -0
- package/dist/index.js +21 -3
- package/dist/launch.js +29 -0
- package/package.json +1 -1
- package/version-policy.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"cliVersion":"0.1.6","bundledAt":"2026-05-25T09:55:59Z"}
|
|
@@ -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
|
-
|
|
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
|
|
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,
|
|
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
|
|
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.
|
|
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
package/version-policy.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"minCliVersion": "0.1.4",
|
|
3
3
|
"minAppVersion": "0.2.2",
|
|
4
|
-
"latestCliVersion": "0.1.
|
|
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 до последней сборки."
|