cursorconnect 0.1.6 → 0.1.8

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 (55) hide show
  1. package/bridge-runtime/.env.example +14 -2
  2. package/bridge-runtime/connector-version.json +1 -1
  3. package/bridge-runtime/dist/agent-completion-push.d.ts +35 -0
  4. package/bridge-runtime/dist/agent-completion-push.js +195 -0
  5. package/bridge-runtime/dist/agent-title-match.d.ts +8 -7
  6. package/bridge-runtime/dist/agent-title-match.js +11 -1
  7. package/bridge-runtime/dist/chat-display-store.d.ts +21 -9
  8. package/bridge-runtime/dist/chat-display-store.js +97 -23
  9. package/bridge-runtime/dist/chat-display.d.ts +2 -0
  10. package/bridge-runtime/dist/chat-display.js +197 -33
  11. package/bridge-runtime/dist/chat-history-mode.d.ts +5 -0
  12. package/bridge-runtime/dist/chat-history-mode.js +7 -0
  13. package/bridge-runtime/dist/command-executor.d.ts +2 -0
  14. package/bridge-runtime/dist/command-executor.js +44 -0
  15. package/bridge-runtime/dist/composer-title-index.d.ts +1 -0
  16. package/bridge-runtime/dist/composer-title-index.js +7 -7
  17. package/bridge-runtime/dist/config.js +2 -0
  18. package/bridge-runtime/dist/connector-client-version.js +1 -1
  19. package/bridge-runtime/dist/debug-chats-page.d.ts +2 -0
  20. package/bridge-runtime/dist/debug-chats-page.js +491 -0
  21. package/bridge-runtime/dist/dom-transcript-store.d.ts +17 -0
  22. package/bridge-runtime/dist/dom-transcript-store.js +76 -0
  23. package/bridge-runtime/dist/extract-page.js +56 -85
  24. package/bridge-runtime/dist/history-limit.d.ts +2 -0
  25. package/bridge-runtime/dist/history-limit.js +2 -0
  26. package/bridge-runtime/dist/history-request.d.ts +8 -0
  27. package/bridge-runtime/dist/history-request.js +7 -0
  28. package/bridge-runtime/dist/index.js +10 -0
  29. package/bridge-runtime/dist/jsonl-index.d.ts +21 -3
  30. package/bridge-runtime/dist/jsonl-index.js +237 -73
  31. package/bridge-runtime/dist/jsonl-live-debug.d.ts +24 -0
  32. package/bridge-runtime/dist/jsonl-live-debug.js +175 -0
  33. package/bridge-runtime/dist/keep-awake.d.ts +5 -0
  34. package/bridge-runtime/dist/keep-awake.js +48 -0
  35. package/bridge-runtime/dist/media-path.d.ts +2 -0
  36. package/bridge-runtime/dist/media-path.js +17 -0
  37. package/bridge-runtime/dist/message-filter.d.ts +2 -0
  38. package/bridge-runtime/dist/message-filter.js +21 -5
  39. package/bridge-runtime/dist/pairing-code.d.ts +2 -0
  40. package/bridge-runtime/dist/pairing-code.js +9 -2
  41. package/bridge-runtime/dist/relay-upstream.d.ts +5 -1
  42. package/bridge-runtime/dist/relay-upstream.js +25 -1
  43. package/bridge-runtime/dist/relay.d.ts +31 -0
  44. package/bridge-runtime/dist/relay.js +401 -32
  45. package/bridge-runtime/dist/types.d.ts +25 -0
  46. package/bridge-runtime/selectors.json +4 -5
  47. package/dist/index.js +79 -20
  48. package/dist/launch.js +23 -5
  49. package/dist/macos-autostart.js +87 -0
  50. package/dist/pairing-code.js +12 -3
  51. package/dist/print-pairing.js +2 -0
  52. package/dist/run-service.js +31 -0
  53. package/dist/startup-check.js +165 -0
  54. package/package.json +1 -1
  55. package/version-policy.json +2 -2
@@ -21,6 +21,23 @@ export function normalizeMediaRef(src) {
21
21
  return path.normalize(fsPath);
22
22
  return null;
23
23
  }
24
+ /** One path per file for merge/dedupe (JSONL absolute vs DOM vscode-file://). */
25
+ export function canonicalizeImagePaths(paths) {
26
+ const out = [];
27
+ const seen = new Set();
28
+ for (const raw of paths) {
29
+ const trimmed = raw.trim();
30
+ if (!trimmed)
31
+ continue;
32
+ const canon = normalizeMediaRef(trimmed) ??
33
+ (path.isAbsolute(trimmed) ? path.normalize(trimmed) : trimmed);
34
+ if (seen.has(canon))
35
+ continue;
36
+ seen.add(canon);
37
+ out.push(canon);
38
+ }
39
+ return out;
40
+ }
24
41
  /** Resolve query `path` from client (absolute path or vscode-file URL). */
25
42
  export function resolveMediaPathParam(rawPath) {
26
43
  const trimmed = rawPath.trim();
@@ -16,6 +16,8 @@ export declare function textImpliesAgentWorking(text: string): boolean;
16
16
  /** Cursor JSONL redacts tool/thinking tails as `[REDACTED]` — not shown in live DOM. */
17
17
  export declare function stripJsonlRedactionArtifacts(text: string): string;
18
18
  export declare function isNoiseChatText(text: string): boolean;
19
+ /** Markdown / structured answer — must stay in chat lenta even if it mentions bridge symbols. */
20
+ export declare function isUserFacingAssistantProse(text: string): boolean;
19
21
  /** Chain-of-thought / tool trace rows — not user-facing answers (DOM + JSONL). */
20
22
  export declare function isAssistantReflectionText(text: string): boolean;
21
23
  /** Short agent status worth showing (not tool log). */
@@ -7,7 +7,7 @@ const EDITED_DIFF = /^Edited\s+.+\s*\+\d+/i;
7
7
  const FILE_DIFF = /\.[a-z0-9]+\s*[+-]\d+/i;
8
8
  const TOOL_COMMAND = /^(cd |npm |npx |curl |git |node )/i;
9
9
  /** Cursor pauses chat while background agent / shell runs */
10
- export const BACKGROUND_WORK_STATUS = /will resume when|background work finishes|background shell|resuming when|paused while|waiting for background/i;
10
+ export const BACKGROUND_WORK_STATUS = /will resume when|background work finishes|background shell|resuming when|paused while|waiting for background|waiting for \d+ command/i;
11
11
  export const AGENT_STATUS_BACKGROUND_SHELL = 'background_shell';
12
12
  export const WORKING_STATUS_LINE = /^working\.?$/i;
13
13
  /** Short DOM status line only — not a sentence inside a chat message. */
@@ -72,11 +72,31 @@ export function isNoiseChatText(text) {
72
72
  return true;
73
73
  return false;
74
74
  }
75
+ /** Markdown / structured answer — must stay in chat lenta even if it mentions bridge symbols. */
76
+ export function isUserFacingAssistantProse(text) {
77
+ const t = stripJsonlRedactionArtifacts(text).trim();
78
+ if (!t)
79
+ return false;
80
+ if (/^##\s+\S/m.test(t))
81
+ return true;
82
+ if (/^\*\*[^*]{2,}\*\*/m.test(t) && t.length >= 60)
83
+ return true;
84
+ const tableRows = t.match(/^\|[^\n]+\|$/gm);
85
+ if (tableRows && tableRows.length >= 2)
86
+ return true;
87
+ if (/^[-*]\s+\S/m.test(t) && t.length >= 100)
88
+ return true;
89
+ if (/^(?:\d+\.\s+\S|>\s)/m.test(t) && t.length >= 150)
90
+ return true;
91
+ return false;
92
+ }
75
93
  /** Chain-of-thought / tool trace rows — not user-facing answers (DOM + JSONL). */
76
94
  export function isAssistantReflectionText(text) {
77
95
  const t = stripJsonlRedactionArtifacts(text).trim().replace(/\s+/g, ' ');
78
96
  if (!t || isNoiseChatText(t))
79
97
  return true;
98
+ if (isUserFacingAssistantProse(t))
99
+ return false;
80
100
  if (/^Thought\s*for\s*\d/i.test(t) && t.length < 160)
81
101
  return true;
82
102
  if (/^(Exploring|Grepped|Searched|Listed|Read |Ran |Edited |Loading|Planning|Using image)/i.test(t)) {
@@ -85,10 +105,6 @@ export function isAssistantReflectionText(text) {
85
105
  const toolHits = t.match(/\b(Explored|Grepped|Searched|Listed|Read )\b/gi);
86
106
  if (toolHits && toolHits.length >= 2)
87
107
  return true;
88
- if (t.length > 160 &&
89
- /\b(state\.messages|flat-index|mapKeyedChildren|humanEl|extract-page|userMessagesEquivalent)\b/i.test(t)) {
90
- return true;
91
- }
92
108
  return false;
93
109
  }
94
110
  /** Short agent status worth showing (not tool log). */
@@ -1,3 +1,5 @@
1
1
  export declare const PAIRING_CODE_LENGTH = 6;
2
+ /** @see connect/src/pairing-code.ts — keep in sync */
3
+ export declare const PAIRING_CODE_ALPHABET = "ACDEFHJKMNPRTUVWXY3479";
2
4
  export declare function generatePairingCode(): string;
3
5
  export declare function normalizePairingCode(raw: string): string | null;
@@ -1,11 +1,14 @@
1
1
  import { randomBytes } from 'crypto';
2
2
  export const PAIRING_CODE_LENGTH = 6;
3
- const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
3
+ /** @see connect/src/pairing-code.ts — keep in sync */
4
+ export const PAIRING_CODE_ALPHABET = 'ACDEFHJKMNPRTUVWXY3479';
5
+ const ALPHABET_SET = new Set(PAIRING_CODE_ALPHABET.split(''));
4
6
  export function generatePairingCode() {
5
7
  const bytes = randomBytes(PAIRING_CODE_LENGTH);
8
+ const n = PAIRING_CODE_ALPHABET.length;
6
9
  let out = '';
7
10
  for (let i = 0; i < PAIRING_CODE_LENGTH; i++) {
8
- out += ALPHABET[bytes[i] % ALPHABET.length];
11
+ out += PAIRING_CODE_ALPHABET[bytes[i] % n];
9
12
  }
10
13
  return out;
11
14
  }
@@ -13,5 +16,9 @@ export function normalizePairingCode(raw) {
13
16
  const code = raw.replace(/[^a-zA-Z0-9]/g, '').toUpperCase();
14
17
  if (code.length !== PAIRING_CODE_LENGTH)
15
18
  return null;
19
+ for (const ch of code) {
20
+ if (!ALPHABET_SET.has(ch))
21
+ return null;
22
+ }
16
23
  return code;
17
24
  }
@@ -3,10 +3,14 @@ export type UpstreamCommandHandler = (event: string, ...args: unknown[]) => void
3
3
  export declare class RelayUpstream {
4
4
  private config;
5
5
  private onClientEvent;
6
+ private onConnect?;
6
7
  private socket;
7
- constructor(config: ServerConfig, onClientEvent: UpstreamCommandHandler);
8
+ private keepaliveTimer;
9
+ constructor(config: ServerConfig, onClientEvent: UpstreamCommandHandler, onConnect?: (() => void) | undefined);
8
10
  private registerPairing;
9
11
  connect(): void;
12
+ private startKeepalive;
13
+ private stopKeepalive;
10
14
  emit(event: string, ...args: unknown[]): void;
11
15
  get connected(): boolean;
12
16
  private handleHttpProxy;
@@ -12,10 +12,13 @@ const CLIENT_EVENTS = [
12
12
  export class RelayUpstream {
13
13
  config;
14
14
  onClientEvent;
15
+ onConnect;
15
16
  socket = null;
16
- constructor(config, onClientEvent) {
17
+ keepaliveTimer = null;
18
+ constructor(config, onClientEvent, onConnect) {
17
19
  this.config = config;
18
20
  this.onClientEvent = onClientEvent;
21
+ this.onConnect = onConnect;
19
22
  }
20
23
  registerPairing() {
21
24
  if (!this.socket?.connected)
@@ -59,6 +62,7 @@ export class RelayUpstream {
59
62
  this.socket.on('connect', () => {
60
63
  console.log(`[relay-upstream] connected to ${url} room=${this.config.relayRoomId}`);
61
64
  this.registerPairing();
65
+ this.onConnect?.();
62
66
  });
63
67
  this.socket.on('connect_error', (err) => {
64
68
  const v = connectorClientVersion();
@@ -82,6 +86,26 @@ export class RelayUpstream {
82
86
  this.socket.on('relay:http', (req) => {
83
87
  void this.handleHttpProxy(req);
84
88
  });
89
+ this.startKeepalive();
90
+ }
91
+ startKeepalive() {
92
+ this.stopKeepalive();
93
+ const ms = this.config.relayKeepaliveMs;
94
+ if (!this.config.relayUrl || ms <= 0)
95
+ return;
96
+ this.keepaliveTimer = setInterval(() => {
97
+ if (!this.socket?.connected)
98
+ return;
99
+ this.socket.emit('relay:connector-ping', {
100
+ roomId: this.config.relayRoomId,
101
+ ts: Date.now(),
102
+ });
103
+ }, ms);
104
+ }
105
+ stopKeepalive() {
106
+ if (this.keepaliveTimer)
107
+ clearInterval(this.keepaliveTimer);
108
+ this.keepaliveTimer = null;
85
109
  }
86
110
  emit(event, ...args) {
87
111
  if (this.socket?.connected)
@@ -23,14 +23,43 @@ export declare class Relay {
23
23
  private io;
24
24
  private tokens;
25
25
  private upstream;
26
+ private agentCompletionPush;
27
+ private readonly pendingPushPayloads;
26
28
  private readonly chatDisplay;
29
+ /** Raw JSONL row count last sent per agent (live `append` emits). */
30
+ private readonly lastEmittedJsonlRows;
31
+ /** Last display tail pushed to app — re-emit when user/assistant tail changes. */
32
+ private readonly lastEmittedLentaSig;
33
+ /** Display bubble count last sent — block regression 214→74 style wipes on phone. */
34
+ private readonly lastEmittedHistLen;
35
+ private domOverlayTimer;
27
36
  constructor(config: ServerConfig, stateManager: StateManager, commandExecutor: CommandExecutor, cdpBridge: CDPBridge, jsonlIndex: JsonlIndex, messageDebugStore: MessageDebugStore, domExtractor: DOMExtractor);
37
+ private emitAgentCompletedPush;
38
+ private flushPendingPushPayloads;
39
+ private observeAgentCompletionForPush;
28
40
  listen(): Promise<void>;
29
41
  private get authEnabled();
42
+ /** Read-only view of in-memory bridge state (no writes to stores). */
43
+ private readOnlyChatSnapshot;
44
+ /** Push JSONL file updates to every subscribed route id (e.g. sidebar-0) for that composer. */
45
+ private syncJsonlToSubscribedAgents;
46
+ /** JSONL baseline + DOM rows not yet in file (`liveMessages`). */
47
+ private lentaSnapshot;
48
+ private emitLentaForAgent;
49
+ private lentaTailSignature;
50
+ /** Live JSONL → `agent:messages` for subscribed chats (phone lenta). */
51
+ private emitJsonlLiveForAgent;
52
+ private scheduleDomOverlayEmit;
53
+ /** DOM poll while agent works — overlay until the same turn lands in JSONL. */
54
+ private emitDomOverlayForSyncedSubscribers;
55
+ private agentMessagesSnapshot;
30
56
  private checkMediaAuth;
31
57
  private setupHttp;
32
58
  private setupSocket;
33
59
  private broadcast;
60
+ private historySeqByAgent;
61
+ private nextHistorySeq;
62
+ private emitAgentMessages;
34
63
  private prepareStateMessages;
35
64
  private withDisplayState;
36
65
  private wireEvents;
@@ -44,6 +73,8 @@ export declare class Relay {
44
73
  private runCommand;
45
74
  private runAgentsHistory;
46
75
  private runAgentsSubscribe;
76
+ /** Открытие чата: JSONL baseline + focus/scroll (DOM poll только для state: working/approve). */
77
+ private refreshDomChatOnSubscribe;
47
78
  private runAgentsUnsubscribe;
48
79
  private runAgentsFocus;
49
80
  }