cursorconnect 0.1.4 → 0.1.5

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # cursorconnect
2
2
 
3
- CLI для Mac: bridge в фоне, pairing (QR + код), Cursor с CDP.
3
+ CLI для Mac: Cursor Connect в фоне, pairing (код), Cursor с CDP.
4
4
 
5
5
  ## Установка (пользователи)
6
6
 
@@ -24,7 +24,7 @@ npm run install:cli
24
24
  ## Команды
25
25
 
26
26
  ```bash
27
- cursorconnect start # CDP (авто Cmd+Q + Cursor с :9222) + bridge + код
27
+ cursorconnect start # CDP (авто Cmd+Q + Cursor с :9222) + Cursor Connect + код
28
28
  cursorconnect start -r # то же (явный перезапуск)
29
29
  cursorconnect start --no-restart-cursor # не трогать Cursor (спросит y/n)
30
30
  cursorconnect status
package/dist/big-code.js CHANGED
@@ -1,5 +1,5 @@
1
- /** 5×5 block digits for terminal pairing code. */
2
- const DIGITS = {
1
+ /** 5×5 block glyphs (█) for pairing code — A–Z and 0–9. */
2
+ const GLYPHS = {
3
3
  '0': ['█████', '█ █', '█ █', '█ █', '█████'],
4
4
  '1': [' █ ', ' ██ ', ' █ ', ' █ ', ' ███ '],
5
5
  '2': ['█████', ' █', '█████', '█ ', '█████'],
@@ -10,13 +10,44 @@ const DIGITS = {
10
10
  '7': ['█████', ' █', ' █ ', ' █ ', ' █ '],
11
11
  '8': ['█████', '█ █', '█████', '█ █', '█████'],
12
12
  '9': ['█████', '█ █', '█████', ' █', '█████'],
13
+ A: [' ███ ', '█ █', '█████', '█ █', '█ █'],
14
+ B: ['████ ', '█ █', '████ ', '█ █', '████ '],
15
+ C: [' ████', '█ ', '█ ', '█ ', ' ████'],
16
+ D: ['████ ', '█ █', '█ █', '█ █', '████ '],
17
+ E: ['█████', '█ ', '████ ', '█ ', '█████'],
18
+ F: ['█████', '█ ', '████ ', '█ ', '█ '],
19
+ G: [' ████', '█ ', '█ ██', '█ █', ' ████'],
20
+ H: ['█ █', '█ █', '█████', '█ █', '█ █'],
21
+ I: [' ███ ', ' █ ', ' █ ', ' █ ', ' ███ '],
22
+ J: [' ███', ' █', ' █', '█ █', ' ███ '],
23
+ K: ['█ █', '█ █ ', '███ ', '█ █ ', '█ █'],
24
+ L: ['█ ', '█ ', '█ ', '█ ', '█████'],
25
+ M: ['█ █', '██ ██', '█ █ █', '█ █', '█ █'],
26
+ N: ['█ █', '██ █', '█ █ █', '█ ██', '█ █'],
27
+ O: [' ███ ', '█ █', '█ █', '█ █', ' ███ '],
28
+ P: ['████ ', '█ █', '████ ', '█ ', '█ '],
29
+ Q: [' ███ ', '█ █', '█ █', '█ ██', ' ████'],
30
+ R: ['████ ', '█ █', '████ ', '█ █ ', '█ █'],
31
+ S: [' ████', '█ ', ' ███ ', ' █', '████ '],
32
+ T: ['█████', ' █ ', ' █ ', ' █ ', ' █ '],
33
+ U: ['█ █', '█ █', '█ █', '█ █', ' ███ '],
34
+ V: ['█ █', '█ █', '█ █', ' █ █ ', ' █ '],
35
+ W: ['█ █', '█ █', '█ █ █', '██ ██', '█ █'],
36
+ X: ['█ █', ' █ █ ', ' █ ', ' █ █ ', '█ █'],
37
+ Y: ['█ █', ' █ █ ', ' █ ', ' █ ', ' █ '],
38
+ Z: ['█████', ' █ ', ' █ ', ' █ ', '█████'],
13
39
  };
40
+ const FALLBACK = GLYPHS['8'];
14
41
  const GAP = ' ';
15
42
  export function renderBigCode(code) {
16
- const digits = code.replace(/\D/g, '').slice(0, 6);
43
+ const chars = code
44
+ .toUpperCase()
45
+ .replace(/[^A-Z0-9]/g, '')
46
+ .slice(0, 6)
47
+ .split('');
17
48
  const rows = ['', '', '', '', ''];
18
- for (const ch of digits) {
19
- const art = DIGITS[ch] ?? DIGITS['8'];
49
+ for (const ch of chars) {
50
+ const art = GLYPHS[ch] ?? FALLBACK;
20
51
  for (let i = 0; i < 5; i++) {
21
52
  rows[i] += art[i] + GAP;
22
53
  }
@@ -51,7 +51,7 @@ export function resolveBridgeDir() {
51
51
  if (isValidBridgeDir(bridge))
52
52
  return bridge;
53
53
  }
54
- throw new Error('Не найден bridge.\n' +
54
+ throw new Error('Не найден Cursor Connect (bridge).\n' +
55
55
  ' npm install -g cursorconnect && cursorconnect start\n' +
56
56
  ' (для разработки: клон репо + npm install в корне)');
57
57
  }
package/dist/diagnose.js CHANGED
@@ -117,7 +117,7 @@ export async function runDiagnose() {
117
117
  ok: ok && Boolean(j.connectorInRoom) && Boolean(j.tokenRegistered),
118
118
  detail: JSON.stringify(j),
119
119
  hint: !j.connectorInRoom
120
- ? 'Bridge не в этой комнате на relay'
120
+ ? 'Cursor Connect не в этой комнате на relay'
121
121
  : !j.tokenRegistered
122
122
  ? 'Токен не зарегистрирован — перезапустите cursorconnect start'
123
123
  : !j.tokenAccepted
@@ -138,7 +138,7 @@ export async function runDiagnose() {
138
138
  const res = await fetch('http://127.0.0.1:3847/health');
139
139
  const j = (await res.json());
140
140
  checks.push({
141
- id: 'bridge.local',
141
+ id: 'cursor-connect.local',
142
142
  ok: Boolean(j.ok),
143
143
  detail: `ok=${j.ok} cdp=${j.cdp}`,
144
144
  hint: j.cdp ? undefined : 'Cursor с --remote-debugging-port=9222',
@@ -146,7 +146,7 @@ export async function runDiagnose() {
146
146
  }
147
147
  catch (e) {
148
148
  checks.push({
149
- id: 'bridge.local',
149
+ id: 'cursor-connect.local',
150
150
  ok: false,
151
151
  detail: e.message,
152
152
  hint: 'cursorconnect start',
@@ -201,7 +201,7 @@ export async function runDiagnose() {
201
201
  id: 'socket.history',
202
202
  ok: history.ok,
203
203
  detail: history.detail,
204
- hint: history.ok ? undefined : 'connectorInRoom false или bridge не отвечает — cursorconnect start',
204
+ hint: history.ok ? undefined : 'connectorInRoom false или Cursor Connect не отвечает — cursorconnect start',
205
205
  });
206
206
  return { at: new Date().toISOString(), relayUrl, roomId, checks };
207
207
  }
package/dist/index.js CHANGED
@@ -54,32 +54,26 @@ async function cmdStart(argv) {
54
54
  noRestartCursor,
55
55
  });
56
56
  if (!cdpPortOk) {
57
- console.warn('[cursorconnect] CDP порт недоступен — bridge запустится, список чатов будет из архива JSONL.');
57
+ console.warn('[cursorconnect] CDP порт недоступен — Cursor Connect запустится, список чатов будет из архива JSONL.');
58
58
  }
59
59
  if (isBridgeRunning()) {
60
- console.log('Перезапуск bridge…');
60
+ console.error('[cursorconnect] Перезапуск Cursor Connect…');
61
61
  stopBridge();
62
62
  }
63
63
  startBridge(env);
64
- console.log(`Bridge в фоне ${BRIDGE_LOG_FILE}`);
65
- // 2) Ждём, пока bridge реально подключится к workbench (health.cdp), не только :9222.
66
- const health = await waitBridgeHealth(45_000, { requireCdp: cdpPortOk });
67
- const connectorOk = await waitRelayConnector(relayUrl, 30_000);
68
- const cdpReady = cdpPortOk && health.cdp;
69
- if (cdpPortOk && !health.cdp) {
70
- console.warn('[cursorconnect] Порт 9222 открыт, но bridge не подключился к Cursor (cdp:false). ' +
71
- 'Проверьте: cursorconnect status · tail -f ' +
72
- BRIDGE_LOG_FILE);
64
+ let health = await waitBridgeHealth(12_000, { requireCdp: false });
65
+ if (health.ok && cdpPortOk && !health.cdp) {
66
+ health = await waitBridgeHealth(15_000, { requireCdp: true });
73
67
  }
74
- printPairingToTerminal(refreshed, {
75
- bridge: health.ok,
76
- cdp: cdpReady,
77
- connector: connectorOk,
78
- });
68
+ await waitRelayConnector(relayUrl, 12_000);
69
+ if (cdpPortOk && health.ok && !health.cdp) {
70
+ console.error(`[cursorconnect] CDP не подключён (cdp:false) · лог: ${BRIDGE_LOG_FILE}`);
71
+ }
72
+ printPairingToTerminal(refreshed);
79
73
  }
80
74
  async function cmdStop() {
81
75
  stopBridge();
82
- console.log('Bridge остановлен');
76
+ console.log('Cursor Connect остановлен');
83
77
  }
84
78
  async function cmdInit(pathArg) {
85
79
  const target = pathArg?.trim() || process.cwd();
@@ -104,43 +98,12 @@ async function cmdDiagnose() {
104
98
  async function cmdStatus() {
105
99
  const identity = loadPairingIdentity();
106
100
  ensureUserConfig();
107
- const bridgeDotEnv = join(resolveBridgeDir(), '.env');
108
- const { relayUrl } = resolveRelayConfig([bridgeDotEnv]);
109
- console.log('Bridge running:', isBridgeRunning());
110
101
  if (!identity) {
111
- console.log('Identity не найден — запустите: cursorconnect start');
112
- return;
113
- }
114
- let connector = false;
115
- let cdp = false;
116
- let bridgeOk = false;
117
- try {
118
- const h = await fetch('http://127.0.0.1:3847/health');
119
- const j = (await h.json());
120
- bridgeOk = Boolean(j.ok);
121
- cdp = Boolean(j.cdp);
122
- }
123
- catch {
124
- /* offline */
125
- }
126
- if (relayUrl) {
127
- try {
128
- const res = await fetch(`${relayUrl.replace(/\/$/, '')}/health`);
129
- const j = (await res.json());
130
- connector = Boolean(j.connector);
131
- }
132
- catch {
133
- /* ignore */
134
- }
135
- printPairingToTerminal(identity, { bridge: bridgeOk, cdp, connector });
136
- }
137
- else {
138
- printPairingToTerminal(identity, {
139
- bridge: bridgeOk,
140
- cdp,
141
- connector: false,
142
- });
102
+ console.error('Identity не найден — запустите: cursorconnect start');
103
+ process.exit(1);
143
104
  }
105
+ console.error(`[cursorconnect] Cursor Connect работает: ${isBridgeRunning()}`);
106
+ printPairingToTerminal(identity);
144
107
  }
145
108
  async function main() {
146
109
  const argv = process.argv.slice(2);
@@ -165,12 +128,12 @@ async function main() {
165
128
  default:
166
129
  console.log(`Usage: cursorconnect <command>
167
130
 
168
- start — CDP (авто-перезапуск Cursor) + bridge + код
131
+ start — CDP (авто-перезапуск Cursor) + Cursor Connect + код
169
132
  start -r — то же (явный перезапуск Cursor)
170
133
  start --no-restart-cursor — не трогать Cursor (спросит y/n в TTY)
171
- stop — остановить bridge
134
+ stop — остановить Cursor Connect
172
135
  status — код и статус
173
- diagnose — проверка relay / bridge / socket (без гаданий)
136
+ diagnose — проверка relay / Cursor Connect / socket (без гаданий)
174
137
  init [path] — только для разработки (клон репо)
175
138
 
176
139
  Установка (из любой папки):
package/dist/launch.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { execSync, spawn, spawnSync } from 'child_process';
2
2
  import { askYesNo } from './ask.js';
3
- import { existsSync, openSync, readFileSync, writeFileSync } from 'fs';
3
+ import { closeSync, existsSync, openSync, readFileSync, writeFileSync } from 'fs';
4
4
  import { BRIDGE_LOG_FILE, BRIDGE_PID_FILE } from './paths.js';
5
5
  import { resolveBridgeDir } from './bridge-dir.js';
6
6
  export function isBridgeRunning() {
@@ -59,6 +59,12 @@ export function startBridge(env) {
59
59
  stdio: ['ignore', logFd, logFd],
60
60
  });
61
61
  child.unref();
62
+ try {
63
+ closeSync(logFd);
64
+ }
65
+ catch {
66
+ /* ignore */
67
+ }
62
68
  writeFileSync(BRIDGE_PID_FILE, String(child.pid));
63
69
  return child;
64
70
  }
@@ -1,5 +1,6 @@
1
1
  import { randomBytes, randomUUID } from 'crypto';
2
2
  import { generatePairingCode } from './pairing-code.js';
3
+ import { PAIRING_CODE_TTL_MS } from './pairing-ttl.js';
3
4
  import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
4
5
  import { homedir, hostname } from 'os';
5
6
  import { join } from 'path';
@@ -33,7 +34,7 @@ export function ensurePairingIdentity(machineLabel) {
33
34
  clientToken: randomBytes(32).toString('hex'),
34
35
  machineLabel: machineLabel?.trim() || defaultMachineLabel(),
35
36
  pairingCode: generatePairingCode(),
36
- pairingCodeExpiresAt: Date.now() + 10 * 60_000,
37
+ pairingCodeExpiresAt: Date.now() + PAIRING_CODE_TTL_MS,
37
38
  createdAt: now,
38
39
  updatedAt: now,
39
40
  };
@@ -45,7 +46,7 @@ export function refreshPairingCode(identity, machineLabel) {
45
46
  ...identity,
46
47
  machineLabel: machineLabel?.trim() || identity.machineLabel,
47
48
  pairingCode: generatePairingCode(),
48
- pairingCodeExpiresAt: Date.now() + 10 * 60_000,
49
+ pairingCodeExpiresAt: Date.now() + PAIRING_CODE_TTL_MS,
49
50
  updatedAt: new Date().toISOString(),
50
51
  };
51
52
  savePairingIdentity(next);
@@ -0,0 +1,3 @@
1
+ /** Срок жизни pairing-кода (Mac ↔ relay). */
2
+ export const PAIRING_CODE_TTL_MS = 10 * 60_000;
3
+ export const PAIRING_CODE_TTL_MINUTES = 10;
@@ -1,35 +1,26 @@
1
- export function printPairingToTerminal(identity, status) {
2
- const expiresIn = Math.max(0, Math.floor((identity.pairingCodeExpiresAt - Date.now()) / 1000));
3
- const ready = status.bridge && status.cdp && status.connector;
4
- const code = identity.pairingCode;
5
- console.log('\n────────────────────────────────────────');
6
- console.log(' CursorConnect');
1
+ import { renderBigCode } from './big-code.js';
2
+ import { PAIRING_CODE_TTL_MINUTES } from './pairing-ttl.js';
3
+ /** Pairing code: plain ASCII (A–Z, 0–9) for app input. */
4
+ function pairingCodeAscii(code) {
5
+ return code.replace(/[^A-Z0-9]/g, '').slice(0, 6);
6
+ }
7
+ export function printPairingToTerminal(identity) {
8
+ const code = pairingCodeAscii(identity.pairingCode);
9
+ console.log('Cursor Connect запущен в фоне');
10
+ console.log('');
11
+ console.log('────────────────────────────────────────');
12
+ console.log('');
7
13
  console.log(` Компьютер: ${identity.machineLabel}`);
8
14
  console.log('');
9
- console.log(' Введите код в приложении CursorConnect:');
15
+ console.log(' Введите код в приложении Cursor Connect:');
10
16
  console.log('');
11
- console.log(` ${code}`);
17
+ console.log(renderBigCode(code));
12
18
  console.log('');
13
- console.log(' Код одноразовый — после подключения снова: cursorconnect start');
14
- console.log(` Действует ~${Math.max(1, Math.floor(expiresIn / 60))} мин`);
15
- if (!ready) {
16
- const parts = [];
17
- if (!status.bridge)
18
- parts.push('bridge');
19
- if (!status.cdp)
20
- parts.push('Cursor');
21
- if (!status.connector)
22
- parts.push('сервер');
23
- console.log('');
24
- console.log(` Ожидание: ${parts.join(', ')}…`);
25
- console.log(' Подождите 10–20 с и снова: cursorconnect status');
26
- }
27
- else {
28
- console.log('');
29
- console.log(' Готово — введите код на телефоне.');
30
- }
19
+ console.log(' Код одноразовый');
20
+ console.log(` Действует ${PAIRING_CODE_TTL_MINUTES} мин`);
31
21
  console.log('');
32
22
  console.log('────────────────────────────────────────');
33
- console.log(' Bridge в фоне · cursorconnect stop');
34
- console.log(' Консоль можно закрыть.\n');
23
+ console.log(' Для остановки Cursor Connect введите cursorconnect stop');
24
+ console.log(' Консоль можно закрыть.');
25
+ console.log('');
35
26
  }
package/dist/repo-root.js CHANGED
@@ -20,7 +20,7 @@ export function loadInstallConfig() {
20
20
  export function saveInstallConfig(repoRoot) {
21
21
  const abs = resolve(repoRoot);
22
22
  if (!isValidRepoRoot(abs)) {
23
- throw new Error(`Не найден bridge в ${abs} (ожидается …/bridge/package.json)`);
23
+ throw new Error(`Не найден Cursor Connect (bridge) в ${abs} (ожидается …/bridge/package.json)`);
24
24
  }
25
25
  mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
26
26
  writeFileSync(CONFIG_FILE, JSON.stringify({ repoRoot: abs }, null, 2), { mode: 0o600 });
@@ -59,7 +59,7 @@ export function resolveRepoRoot() {
59
59
  const fromDev = devRepoRoot();
60
60
  if (fromDev)
61
61
  return fromDev;
62
- throw new Error('Не найден bridge.\n' +
62
+ throw new Error('Не найден Cursor Connect (bridge).\n' +
63
63
  ' npm install -g cursorconnect && cursorconnect start');
64
64
  }
65
65
  export function configFilePath() {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cursorconnect",
3
- "version": "0.1.4",
4
- "description": "CLI: CursorConnect bridge + relay pairing — install once, run from anywhere",
3
+ "version": "0.1.5",
4
+ "description": "CLI: Cursor Connect on Mac + relay pairing — install once, run from anywhere",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "bin": {