cursorconnect 0.1.7 → 0.1.9

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.
Files changed (44) hide show
  1. package/bridge-runtime/.env.example +7 -1
  2. package/bridge-runtime/connector-version.json +1 -1
  3. package/bridge-runtime/dist/agent-completion-push.d.ts +27 -22
  4. package/bridge-runtime/dist/agent-completion-push.js +242 -122
  5. package/bridge-runtime/dist/agent-completion-readiness.d.ts +19 -0
  6. package/bridge-runtime/dist/agent-completion-readiness.js +42 -0
  7. package/bridge-runtime/dist/chat-display-store.d.ts +32 -7
  8. package/bridge-runtime/dist/chat-display-store.js +99 -21
  9. package/bridge-runtime/dist/chat-display.d.ts +36 -0
  10. package/bridge-runtime/dist/chat-display.js +287 -24
  11. package/bridge-runtime/dist/chat-sync.d.ts +3 -1
  12. package/bridge-runtime/dist/chat-sync.js +20 -0
  13. package/bridge-runtime/dist/config.js +2 -0
  14. package/bridge-runtime/dist/connector-client-version.js +1 -1
  15. package/bridge-runtime/dist/debug-chats-page.d.ts +1 -1
  16. package/bridge-runtime/dist/debug-chats-page.js +148 -26
  17. package/bridge-runtime/dist/dom-transcript-store.d.ts +3 -1
  18. package/bridge-runtime/dist/dom-transcript-store.js +18 -3
  19. package/bridge-runtime/dist/extract-page.js +5 -4
  20. package/bridge-runtime/dist/index.js +9 -0
  21. package/bridge-runtime/dist/keep-awake.d.ts +5 -0
  22. package/bridge-runtime/dist/keep-awake.js +48 -0
  23. package/bridge-runtime/dist/lenta-capture.d.ts +46 -0
  24. package/bridge-runtime/dist/lenta-capture.js +146 -0
  25. package/bridge-runtime/dist/lenta-debug.d.ts +42 -0
  26. package/bridge-runtime/dist/lenta-debug.js +221 -0
  27. package/bridge-runtime/dist/lenta-delivery.d.ts +3 -0
  28. package/bridge-runtime/dist/lenta-delivery.js +10 -0
  29. package/bridge-runtime/dist/lenta-seq-journal.d.ts +48 -0
  30. package/bridge-runtime/dist/lenta-seq-journal.js +109 -0
  31. package/bridge-runtime/dist/message-filter.d.ts +5 -0
  32. package/bridge-runtime/dist/message-filter.js +4 -0
  33. package/bridge-runtime/dist/relay-upstream.d.ts +3 -0
  34. package/bridge-runtime/dist/relay-upstream.js +21 -0
  35. package/bridge-runtime/dist/relay.d.ts +47 -3
  36. package/bridge-runtime/dist/relay.js +667 -96
  37. package/bridge-runtime/dist/types.d.ts +13 -4
  38. package/dist/bridge-build.js +50 -0
  39. package/dist/index.js +9 -6
  40. package/dist/launch.js +5 -1
  41. package/dist/run-service.js +10 -4
  42. package/dist/startup-check.js +6 -0
  43. package/package.json +1 -1
  44. package/version-policy.json +2 -2
@@ -33,6 +33,10 @@ export interface ServerConfig {
33
33
  relayUrl: string;
34
34
  relayToken: string;
35
35
  relayRoomId: string;
36
+ /** macOS: prevent system sleep while bridge runs (`KEEP_AWAKE=0` to disable). */
37
+ keepAwakeEnabled: boolean;
38
+ /** Periodic upstream ping when `relayUrl` set; `0` = off. */
39
+ relayKeepaliveMs: number;
36
40
  /** Client token from ~/.cursorconnect/identity.json (relay room pairing). */
37
41
  pairingClientToken?: string;
38
42
  }
@@ -172,6 +176,11 @@ export interface CursorState {
172
176
  pendingQuestionnaire?: PendingQuestionnaire;
173
177
  /** DOM: loading / Stop visible — request in progress */
174
178
  agentWorking?: boolean;
179
+ /**
180
+ * Bridge `ChatDisplayStore` ahead of last `agent:messages` for this agent.
181
+ * App may show «Догружаем ответ…» until cleared.
182
+ */
183
+ lentaPendingByAgent?: Record<string, boolean>;
175
184
  agentStatus?: string;
176
185
  /** DOM status line when agentStatus is background_shell */
177
186
  agentStatusMessage?: string;
@@ -253,14 +262,14 @@ export interface AgentHistory {
253
262
  /** Monotonic per agentId — stale snapshots should be ignored. */
254
263
  seq?: number;
255
264
  }
256
- /** Per-agent chat lenta (JSONL). `state.messages` in state:patch is DOM/debug only. */
265
+ /** Per-agent chat lenta. `state.messages` in state:patch is DOM/debug only. */
257
266
  export interface AgentMessagesPayload {
258
267
  agentId: string;
259
- /** JSONL archive tail (history). When `append`, only new display rows since last emit. */
268
+ /** JSONL baseline rows (debug). */
260
269
  historyMessages: ChatMessage[];
261
- /** Legacy field; always `[]` lenta is JSONL-only. */
270
+ /** DOM overlay rows not yet in JSONL (debug). */
262
271
  liveMessages: ChatMessage[];
263
- /** Same as historyMessages (debug). */
272
+ /** Canonical UI lenta — merge + dedupe + sort on bridge. */
264
273
  messages: ChatMessage[];
265
274
  totalMessages?: number;
266
275
  source: 'dom' | 'jsonl' | 'hybrid';
@@ -0,0 +1,50 @@
1
+ import { execSync } from 'child_process';
2
+ import { existsSync, readdirSync, statSync } from 'fs';
3
+ import { join } from 'path';
4
+ function newestMtimeMs(dir) {
5
+ let max = 0;
6
+ for (const name of readdirSync(dir, { withFileTypes: true })) {
7
+ const path = join(dir, name.name);
8
+ if (name.isDirectory()) {
9
+ max = Math.max(max, newestMtimeMs(path));
10
+ continue;
11
+ }
12
+ if (!name.isFile())
13
+ continue;
14
+ if (!/\.(ts|tsx|json)$/.test(name.name))
15
+ continue;
16
+ max = Math.max(max, statSync(path).mtimeMs);
17
+ }
18
+ return max;
19
+ }
20
+ export function isBridgeSrcNewerThanDist(bridgeDir) {
21
+ const dist = join(bridgeDir, 'dist', 'index.js');
22
+ const src = join(bridgeDir, 'src');
23
+ if (!existsSync(src))
24
+ return false;
25
+ if (!existsSync(dist))
26
+ return true;
27
+ return newestMtimeMs(src) > statSync(dist).mtimeMs;
28
+ }
29
+ export function buildBridge(bridgeDir) {
30
+ const monorepoRoot = join(bridgeDir, '..');
31
+ const hasWorkspace = existsSync(join(monorepoRoot, 'package.json')) &&
32
+ existsSync(join(monorepoRoot, 'bridge', 'package.json'));
33
+ if (hasWorkspace) {
34
+ execSync('npm run build -w bridge', {
35
+ cwd: monorepoRoot,
36
+ stdio: 'inherit',
37
+ });
38
+ return;
39
+ }
40
+ execSync('npm run build', { cwd: bridgeDir, stdio: 'inherit' });
41
+ }
42
+ /** Dev: compile bridge when `src/` is newer than `dist/` (runtime = dist, not ts). */
43
+ export function ensureBridgeBuilt(bridgeDir) {
44
+ if (process.env.CURSORCONNECT_SKIP_BRIDGE_BUILD === '1')
45
+ return;
46
+ if (!isBridgeSrcNewerThanDist(bridgeDir))
47
+ return;
48
+ console.error('[cursorconnect] bridge/src новее dist — сборка…');
49
+ buildBridge(bridgeDir);
50
+ }
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, } from './launch.js';
4
+ import { ensureCursorCdp, isBridgeRunning, printManualCdpInstructions, startBridge, stopBridge, } 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';
@@ -60,7 +60,13 @@ async function cmdStart(argv) {
60
60
  noRestartCursor,
61
61
  });
62
62
  if (!cdpPortOk) {
63
- console.warn('[cursorconnect] CDP порт недоступен — Cursor Connect запустится, список чатов будет из архива JSONL.');
63
+ console.error('');
64
+ console.error('[cursorconnect] CDP обязателен — без него Cursor Connect не запускается.');
65
+ console.error(' Cursor с remote debugging (порт 9222), затем снова:');
66
+ console.error(' cursorconnect start');
67
+ console.error('');
68
+ printManualCdpInstructions();
69
+ process.exit(1);
64
70
  }
65
71
  if (isBridgeRunning()) {
66
72
  console.error('[cursorconnect] Перезапуск Cursor Connect…');
@@ -69,15 +75,12 @@ async function cmdStart(argv) {
69
75
  startBridge(env);
70
76
  const readiness = await awaitStartupReadiness(relayUrl, refreshed, {
71
77
  waitMs: 45_000,
72
- requireCdp: cdpPortOk,
78
+ requireCdp: true,
73
79
  });
74
80
  if (!readiness.ready) {
75
81
  printStartupFailure(readiness, BRIDGE_LOG_FILE);
76
82
  process.exit(1);
77
83
  }
78
- if (cdpPortOk && !readiness.localCdp) {
79
- console.warn(`[cursorconnect] CDP не подключён (cdp:false) · лог: ${BRIDGE_LOG_FILE}`);
80
- }
81
84
  console.log('');
82
85
  console.log(' Проверки перед pairing:');
83
86
  for (const line of formatStartupChecklist(readiness)) {
package/dist/launch.js CHANGED
@@ -3,6 +3,7 @@ import { askYesNo } from './ask.js';
3
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
+ import { ensureBridgeBuilt } from './bridge-build.js';
6
7
  export function isBridgeRunning() {
7
8
  if (!existsSync(BRIDGE_PID_FILE))
8
9
  return false;
@@ -51,6 +52,10 @@ export function startBridge(env) {
51
52
  stopBridge();
52
53
  killProcessesOnBridgePort();
53
54
  const bridgeDir = resolveBridgeDir();
55
+ ensureBridgeBuilt(bridgeDir);
56
+ if (!process.env.CURSORCONNECT_BRIDGE_DIR?.trim()) {
57
+ process.env.CURSORCONNECT_BRIDGE_DIR = bridgeDir;
58
+ }
54
59
  const logFd = openLogAppend();
55
60
  const child = spawn('node', ['dist/index.js'], {
56
61
  cwd: bridgeDir,
@@ -243,7 +248,6 @@ export async function ensureCursorCdp(opts = {}) {
243
248
  }
244
249
  }
245
250
  if (!shouldRestart) {
246
- console.warn('[cursorconnect] Cursor без CDP — список чатов будет только из JSONL.');
247
251
  printManualCdpInstructions();
248
252
  return false;
249
253
  }
@@ -1,5 +1,5 @@
1
1
  import { ensurePairingIdentity, refreshPairingCode, } from './pairing-identity.js';
2
- import { isBridgeRunning, startBridge, } from './launch.js';
2
+ import { ensureCursorCdp, isBridgeRunning, startBridge, } from './launch.js';
3
3
  import { BRIDGE_LOG_FILE } from './paths.js';
4
4
  const WATCH_MS = 8_000;
5
5
  function sleep(ms) {
@@ -9,9 +9,15 @@ function sleep(ms) {
9
9
  export async function runServiceLoop(bridgeEnv) {
10
10
  const identity = ensurePairingIdentity();
11
11
  refreshPairingCode(identity);
12
- const boot = () => {
12
+ const boot = async () => {
13
13
  if (isBridgeRunning())
14
14
  return;
15
+ const cdpUrl = bridgeEnv.CDP_URL ?? 'http://127.0.0.1:9222';
16
+ const cdpOk = await ensureCursorCdp({ cdpUrl, noRestartCursor: false });
17
+ if (!cdpOk) {
18
+ console.error('[cursorconnect] service: CDP недоступен — bridge не стартует (нужен порт 9222)');
19
+ return;
20
+ }
15
21
  try {
16
22
  startBridge(bridgeEnv);
17
23
  console.log(`[cursorconnect] service: bridge started → ${BRIDGE_LOG_FILE}`);
@@ -20,12 +26,12 @@ export async function runServiceLoop(bridgeEnv) {
20
26
  console.error('[cursorconnect] service: start failed', e);
21
27
  }
22
28
  };
23
- boot();
29
+ await boot();
24
30
  for (;;) {
25
31
  await sleep(WATCH_MS);
26
32
  if (!isBridgeRunning()) {
27
33
  console.error('[cursorconnect] service: bridge exited, restarting…');
28
- boot();
34
+ await boot();
29
35
  }
30
36
  }
31
37
  }
@@ -39,6 +39,7 @@ export function buildStartupReadiness(identity, local, relay, relayReachable) {
39
39
  const tokensRegistered = relay?.tokensRegistered ?? 0;
40
40
  const tokenRegistered = relay?.tokenRegistered === true;
41
41
  const ready = local.ok &&
42
+ local.cdp &&
42
43
  codeValid &&
43
44
  relayReachable &&
44
45
  connectorInRoom &&
@@ -145,6 +146,11 @@ export function printStartupFailure(r, logPath = BRIDGE_LOG_FILE) {
145
146
  else if (!r.tokenRegistered) {
146
147
  console.error(' Токен не зарегистрирован — перезапустите bridge (cursorconnect start).');
147
148
  }
149
+ if (!r.localCdp) {
150
+ console.error(' CDP недоступен: Cursor должен быть с --remote-debugging-port=9222');
151
+ console.error(` ${'open -a Cursor --args --remote-debugging-port=9222'}`);
152
+ console.error(' Затем: cursorconnect stop && cursorconnect start');
153
+ }
148
154
  if (!r.localBridgeOk) {
149
155
  console.error(` Лог: ${logPath}`);
150
156
  tailLogLines(logPath, 12).forEach((l) => console.error(` ${l}`));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cursorconnect",
3
- "version": "0.1.7",
3
+ "version": "0.1.9",
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
- "minCliVersion": "0.1.4",
2
+ "minCliVersion": "0.1.7",
3
3
  "minAppVersion": "0.2.2",
4
- "latestCliVersion": "0.1.7",
4
+ "latestCliVersion": "0.1.9",
5
5
  "latestAppVersion": "0.2.2",
6
6
  "updateCliCommand": "npm install -g cursorconnect@latest",
7
7
  "updateAppHint": "Обновите CursorConnect в App Store / TestFlight до последней сборки."