@cursorpool-dev/cli 0.5.8 → 0.5.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 (42) hide show
  1. package/node_modules/@cursor-pool/extension/dist/extension.js +46 -116
  2. package/node_modules/@cursor-pool/extension/package.json +3 -3
  3. package/node_modules/@cursor-pool/extension/src/api.ts +2 -17
  4. package/node_modules/@cursor-pool/extension/src/panel.ts +3 -26
  5. package/node_modules/@cursor-pool/extension/test/panel.test.ts +1 -34
  6. package/node_modules/@cursor-pool/patcher/package.json +2 -2
  7. package/node_modules/@cursor-pool/patcher/src/marker.ts +72 -7
  8. package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +80 -17
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
  10. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +151 -149
  11. package/node_modules/@cursor-pool/service/package.json +2 -2
  12. package/node_modules/@cursor-pool/service/src/platformSession.ts +7 -30
  13. package/node_modules/@cursor-pool/service/src/server.ts +1 -1
  14. package/node_modules/@cursor-pool/service/test/platformSession.test.ts +4 -5
  15. package/node_modules/@cursor-pool/service/test/server.test.ts +1 -130
  16. package/node_modules/@cursor-pool/shared/package.json +1 -1
  17. package/node_modules/@cursor-pool/shared/src/manifest.ts +0 -35
  18. package/node_modules/@cursor-pool/shared/test/manifest.test.ts +9 -43
  19. package/package.json +5 -7
  20. package/src/compat.ts +124 -196
  21. package/src/extensionBundle.ts +1 -1
  22. package/src/extensionLink.ts +8 -29
  23. package/src/install.ts +9 -62
  24. package/src/installRecord.ts +0 -2
  25. package/src/patchSet.ts +6 -12
  26. package/src/platform.ts +3 -3
  27. package/src/repair.ts +2 -10
  28. package/src/restore.ts +4 -12
  29. package/src/status.ts +0 -6
  30. package/src/trial.ts +2 -3
  31. package/test/compat.test.ts +59 -195
  32. package/test/e2e-install.test.ts +0 -53
  33. package/test/extensionLink.test.ts +26 -49
  34. package/test/install.test.ts +4 -64
  35. package/test/repair.test.ts +0 -1
  36. package/test/status.test.ts +0 -1
  37. package/test/trial.test.ts +15 -1
  38. package/node_modules/@cursor-pool/takeover-plans/package.json +0 -12
  39. package/node_modules/@cursor-pool/takeover-plans/src/index.ts +0 -22
  40. package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +0 -37
  41. package/node_modules/@cursor-pool/takeover-plans/src/types.ts +0 -9
  42. package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +0 -23
@@ -13,7 +13,6 @@ export type InstallRecord = {
13
13
  appPath: string;
14
14
  cursorVersion: string;
15
15
  cursorCommit: string;
16
- takeoverPlanId: string;
17
16
  targetRelativePath: string;
18
17
  originalSha256: string;
19
18
  compatSupportStatus: CompatibilityManifestEntry['supportStatus'];
@@ -92,7 +91,6 @@ export function isInstallRecordStale(record: InstallRecord | null, actual: Insta
92
91
  'appPath',
93
92
  'cursorVersion',
94
93
  'cursorCommit',
95
- 'takeoverPlanId',
96
94
  'targetRelativePath',
97
95
  'originalSha256',
98
96
  'compatSupportStatus',
package/src/patchSet.ts CHANGED
@@ -144,10 +144,6 @@ export async function patchCursorSet(appPath: string, options: PatchCursorSetOpt
144
144
 
145
145
  export async function restoreCursorSet(appPath: string, options: RestoreCursorSetOptions = {}) {
146
146
  const restoreErrors: unknown[] = [];
147
- const before = await readCursorPatchSetState(appPath, {
148
- platform: options.platform,
149
- workbenchTargetRelativePath: options.workbenchTargetRelativePath,
150
- });
151
147
  const restore = async (operation: () => Promise<unknown>) => {
152
148
  try {
153
149
  await operation();
@@ -156,14 +152,12 @@ export async function restoreCursorSet(appPath: string, options: RestoreCursorSe
156
152
  }
157
153
  };
158
154
 
159
- if (before.patches.some((patch) => patch.name === 'workbench' && patch.markerPresent)) {
160
- await restore(() =>
161
- (options.restoreCursorWorkbenchAuthGate ?? restoreCursorWorkbenchAuthGate)(appPath, {
162
- backupDir: options.backupDir,
163
- targetRelativePath: workbenchRelativePath(options),
164
- }),
165
- );
166
- }
155
+ await restore(() =>
156
+ (options.restoreCursorWorkbenchAuthGate ?? restoreCursorWorkbenchAuthGate)(appPath, {
157
+ backupDir: options.backupDir,
158
+ targetRelativePath: workbenchRelativePath(options),
159
+ }),
160
+ );
167
161
  const alwaysLocalPath = resolveCursorAlwaysLocalPath(appPath, alwaysLocalRelativePath(options));
168
162
  const shouldRestoreAlwaysLocal =
169
163
  Boolean(options.restoreCursorAlwaysLocal) ||
package/src/platform.ts CHANGED
@@ -82,9 +82,9 @@ function buildDeviceInfo() {
82
82
  name: hostname(),
83
83
  os: osPlatform(),
84
84
  arch: arch(),
85
- cliVersion: '0.5.8',
86
- serviceVersion: '0.5.8',
87
- extensionVersion: '0.5.8',
85
+ cliVersion: '0.5.9',
86
+ serviceVersion: '0.5.9',
87
+ extensionVersion: '0.5.9',
88
88
  };
89
89
  }
90
90
 
package/src/repair.ts CHANGED
@@ -69,7 +69,7 @@ export type RepairOptions = FindCursorOptions &
69
69
  adHocResignApp?: typeof adHocResignApp;
70
70
  };
71
71
 
72
- const PACKAGE_VERSION = '0.5.8';
72
+ const PACKAGE_VERSION = '0.5.9';
73
73
 
74
74
  function normalizeAppPath(path: string) {
75
75
  return normalize(path).replace(/\/+$/, '');
@@ -96,10 +96,6 @@ function assertRealRepairInstallRecord(
96
96
  return record;
97
97
  }
98
98
 
99
- function workbenchTargetRelativePathFromCompat(compat: CompatibilityManifestEntry) {
100
- return compat.patchTargets?.find((target) => target.name === 'workbench')?.targetRelativePath;
101
- }
102
-
103
99
  function resolveRepairCompatEntry({
104
100
  cursorVersion,
105
101
  cursorCommit,
@@ -227,7 +223,6 @@ export async function repair(options: RepairOptions = {}) {
227
223
  if (compat.supportStatus === 'blocked' || compat.supportStatus === 'unknown') {
228
224
  throw new Error(`compat: ${compat.supportStatus}`);
229
225
  }
230
- const workbenchTargetRelativePath = workbenchTargetRelativePathFromCompat(compat);
231
226
  const targetPath = join(cursor.appPath, compat.targetRelativePath);
232
227
  const runtimeFile = options.runtimeFile ?? installRecord.runtimeFile ?? DEFAULT_RUNTIME_FILE;
233
228
  const backupDir = options.backupDir ?? installRecord.backupDir;
@@ -261,6 +256,7 @@ export async function repair(options: RepairOptions = {}) {
261
256
  installRecord.originalSha256 && patchState.currentHash === installRecord.originalSha256;
262
257
  if (
263
258
  !patchState.legacyMarkerPresent &&
259
+ compat.expectedSha256 !== '*' &&
264
260
  patchState.currentHash !== compat.expectedSha256 &&
265
261
  !matchesInstallOriginal
266
262
  ) {
@@ -328,8 +324,6 @@ export async function repair(options: RepairOptions = {}) {
328
324
 
329
325
  const patchSetState = await readCursorPatchSetState(cursor.appPath, {
330
326
  agentExecTargetRelativePath: compat.targetRelativePath,
331
- platform: environment.platform,
332
- workbenchTargetRelativePath,
333
327
  });
334
328
 
335
329
  if (patchSetState.allApplied) {
@@ -338,9 +332,7 @@ export async function repair(options: RepairOptions = {}) {
338
332
  } else {
339
333
  const repairedPatchSet = await patchCursorSet(cursor.appPath, {
340
334
  backupDir,
341
- platform: environment.platform,
342
335
  agentExecTargetRelativePath: compat.targetRelativePath,
343
- workbenchTargetRelativePath,
344
336
  patchCursorAgentExec: options.patchCursorAgentExec,
345
337
  patchCursorWorkbenchAuthGate: options.patchCursorWorkbenchAuthGate,
346
338
  });
package/src/restore.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { normalize } from 'node:path';
2
- import { resolveCursorAgentExecPath } from '@cursor-pool/patcher';
2
+ import { restoreCursorAgentExec, resolveCursorAgentExecPath } from '@cursor-pool/patcher';
3
3
  import { DEFAULT_RUNTIME_FILE } from '@cursor-pool/shared/runtime';
4
4
  import {
5
5
  confirmRealOperation,
@@ -14,11 +14,6 @@ import {
14
14
  type InstallRecordOptions,
15
15
  } from './installRecord';
16
16
  import { stopRuntimeService } from './serviceProcess';
17
- import {
18
- formatCursorPatchSetState,
19
- readCursorPatchSetState,
20
- restoreCursorSet,
21
- } from './patchSet';
22
17
  import { resolveCursorTarget, type CursorTargetOptions } from './target';
23
18
  import { assertDisposableCursorAppPath, readTrialRecord, type TrialRecordOptions } from './trial';
24
19
 
@@ -137,12 +132,9 @@ export async function restore(options: RestoreOptions = {}) {
137
132
  });
138
133
  }
139
134
 
140
- await restoreCursorSet(cursor.appPath, {
135
+ const result = await restoreCursorAgentExec(cursor.appPath, {
141
136
  backupDir,
142
- agentExecTargetRelativePath: targetRelativePath,
143
- });
144
- const patchSetState = await readCursorPatchSetState(cursor.appPath, {
145
- agentExecTargetRelativePath: targetRelativePath,
137
+ targetRelativePath,
146
138
  });
147
139
  if (target.mode === 'real') {
148
140
  await stopRuntimeServiceIfRecorded(runtimeFile);
@@ -153,7 +145,7 @@ export async function restore(options: RestoreOptions = {}) {
153
145
  `mode: ${target.mode}`,
154
146
  `app: ${cursor.appPath}`,
155
147
  'restore: ok',
156
- `patch: ${formatCursorPatchSetState(patchSetState)}`,
148
+ `patch: ${result.markerPresent ? 'applied' : 'missing'}`,
157
149
  target.mode === 'real'
158
150
  ? `install-record: ${realInstallRecord ? 'recorded' : 'missing'}`
159
151
  : `trial: ${trialRecord ? 'recorded' : 'missing'}`,
package/src/status.ts CHANGED
@@ -49,10 +49,6 @@ type LatestTakeoverResponse = {
49
49
  };
50
50
  };
51
51
 
52
- function workbenchTargetRelativePathFromCompat(compat: CompatibilityManifestEntry) {
53
- return compat.patchTargets?.find((target) => target.name === 'workbench')?.targetRelativePath;
54
- }
55
-
56
52
  const MAX_CANARY_FIELD_LENGTH = 256;
57
53
 
58
54
  function isSafeCanaryString(value: unknown): value is string {
@@ -162,7 +158,6 @@ export async function status(options: StatusOptions = {}) {
162
158
  fetchManifest: options.fetchCompatManifest,
163
159
  });
164
160
  const compat = resolveCompatEntry(cursor, environment, { entries: compatEntries });
165
- const workbenchTargetRelativePath = workbenchTargetRelativePathFromCompat(compat);
166
161
  const installRecord =
167
162
  target.mode === 'real'
168
163
  ? await readInstallRecord({ installRecordFile: options.installRecordFile })
@@ -194,7 +189,6 @@ export async function status(options: StatusOptions = {}) {
194
189
  const patchSetState = await readCursorPatchSetState(cursor.appPath, {
195
190
  agentExecTargetRelativePath: compat.targetRelativePath,
196
191
  platform: environment.platform,
197
- workbenchTargetRelativePath,
198
192
  });
199
193
  const serviceRunning = await isRuntimeHealthy(runtime);
200
194
  const takeoverStatus = await getTakeoverStatus(runtime, serviceRunning);
package/src/trial.ts CHANGED
@@ -2,7 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
3
3
  import { realpathSync } from 'node:fs';
4
4
  import { homedir } from 'node:os';
5
- import { dirname, join, normalize } from 'node:path';
5
+ import { dirname, join, normalize, resolve } from 'node:path';
6
6
  import { DEFAULT_MACOS_CURSOR_APP_PATH } from './cursor';
7
7
 
8
8
  export type ExtensionState = 'bundled' | 'linked' | 'manual-step-required' | 'missing';
@@ -12,7 +12,6 @@ export type TrialRecord = {
12
12
  appPath: string;
13
13
  cursorVersion: string;
14
14
  cursorCommit: string;
15
- takeoverPlanId: string;
16
15
  targetRelativePath: string;
17
16
  originalSha256: string;
18
17
  compatSupportStatus: 'supported' | 'canary' | 'warning' | 'blocked' | 'unknown';
@@ -40,7 +39,7 @@ function resolveHomePath(path: string) {
40
39
  }
41
40
 
42
41
  function normalizeAppPath(path: string) {
43
- return normalize(path).replace(/\/+$/, '');
42
+ return resolve(normalize(path).replace(/\/+$/, ''));
44
43
  }
45
44
 
46
45
  function isRealCursorAppPath(path: string) {
@@ -15,34 +15,12 @@ import {
15
15
  } from '../src/compat';
16
16
 
17
17
  function remoteRuleFor(cursorVersion: string, cursorCommit: string): CompatibilityManifestEntry {
18
- const cursorMajor = cursorVersion.replace(/^(\d+\.\d+).*/, '$1');
19
- const planByMajor: Record<string, string> = {
20
- '3.5': 'cursor-3.5-mac-agent-f-workbench-p-l0',
21
- '3.6': 'cursor-3.6-mac-agent-c-workbench-h-uv',
22
- '3.7': 'cursor-3.7-mac-agent-et-workbench-wv',
23
- };
24
18
  return {
25
19
  platform: 'darwin',
26
20
  arch: 'arm64',
27
- officialSourceUrl: 'https://cursor.com/download',
28
- officialDownloadUrl: `https://api2.cursor.sh/updates/download/golden/darwin-arm64/cursor/${cursorVersion.replace(/^(\d+\.\d+).*/, '$1')}`,
29
- officialDownloadPlatform: 'darwin-arm64',
30
- verifiedCursorVersion: cursorVersion,
31
- cursorVersion: cursorMajor,
21
+ cursorVersion,
32
22
  cursorCommit,
33
23
  supportStatus: 'supported',
34
- adapterVersion: '0.5.8',
35
- takeoverPlanId: planByMajor[cursorMajor] ?? `cursor-${cursorMajor}-remote-plan`,
36
- structureFamily: 'mac-agent-c-workbench-h-uv',
37
- patchTargets: [
38
- {
39
- name: 'agent-exec',
40
- targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
41
- expectedSha256: 'remote-sha256',
42
- patchStrategy: 'cursor-agent-exec-snippet',
43
- verifyMarker: 'cursor-pool',
44
- },
45
- ],
46
24
  targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
47
25
  expectedSha256: 'remote-sha256',
48
26
  structureSignature: 'remote-structure',
@@ -68,7 +46,7 @@ function signedEnvelope(version: number, rules: CompatibilityManifestEntry[]) {
68
46
  };
69
47
  }
70
48
 
71
- test('default compatibility manifest supports Cursor 3.6.21 on macOS arm64', () => {
49
+ test('default compatibility manifest supports the Cursor 3.6 macOS arm64 version family', () => {
72
50
  const entry = resolveCompatEntry(
73
51
  {
74
52
  appPath: '/Users/example/Desktop/Cursor-Pool-Agent-Canary.app',
@@ -85,89 +63,57 @@ test('default compatibility manifest supports Cursor 3.6.21 on macOS arm64', ()
85
63
  assert.equal(entry.supportStatus, 'supported');
86
64
  assert.equal(entry.requiresAdHocResign, true);
87
65
  assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
88
- assert.equal(
89
- entry.expectedSha256,
90
- '222512631b78fddcdca3fa76c0dd458a7a86751dde19c998ceb31b3fe1905ebf',
91
- );
66
+ assert.equal(entry.cursorVersion, '3.6');
67
+ assert.equal(entry.cursorCommit, '*');
68
+ assert.equal(entry.expectedSha256, '*');
92
69
  assert.equal(
93
70
  DEFAULT_COMPAT_ENTRIES.some(
94
71
  (candidate) =>
72
+ candidate.platform === 'darwin' &&
73
+ candidate.arch === 'arm64' &&
95
74
  candidate.cursorVersion === '3.6' &&
96
- candidate.cursorCommit === 'e7a7e93f4d75f8272503ecf33cedbaae10114a10',
75
+ candidate.cursorCommit === '*',
97
76
  ),
98
77
  true,
99
78
  );
100
79
  });
101
80
 
102
- test('default compatibility entries are keyed by official Cursor major download versions only', () => {
103
- assert.deepEqual(
104
- Array.from(new Set(DEFAULT_COMPAT_ENTRIES.map((entry) => entry.cursorVersion))).sort(),
105
- ['3.4', '3.5', '3.6', '3.7'],
106
- );
107
- assert.equal(
108
- DEFAULT_COMPAT_ENTRIES.every((entry) =>
109
- entry.officialDownloadUrl?.startsWith(
110
- `https://api2.cursor.sh/updates/download/golden/${entry.officialDownloadPlatform}/cursor/${entry.cursorVersion}`,
111
- ),
112
- ),
113
- true,
114
- );
115
- assert.equal(
116
- DEFAULT_COMPAT_ENTRIES.some((entry) => entry.officialSourceUrl !== 'https://cursor.com/download'),
117
- false,
118
- );
119
- assert.equal(
120
- DEFAULT_COMPAT_ENTRIES.some((entry) => entry.platform === 'linux' || entry.platform === 'win32'),
121
- false,
122
- );
123
- });
124
-
125
- test('default compatibility manifest supports Cursor 3.4.20 on macOS arm64 with the v0.4 adapter', () => {
81
+ test('default compatibility manifest supports the Cursor 3.4 macOS arm64 version family', () => {
126
82
  const entry = resolveCompatEntry(
127
83
  {
128
- appPath: '/Applications/Cursor.app',
129
- version: '3.4.20',
130
- commit: '0cf8b06883f54e26bb4f0fb8647c9500ccb43310',
84
+ appPath: '/Users/example/Desktop/Cursor-3.4.0.app',
85
+ version: '3.4.0',
86
+ commit: 'cursor-3-4-family-commit',
131
87
  },
132
88
  {
133
89
  platform: 'darwin',
134
90
  arch: 'arm64',
135
91
  nodeVersion: process.version,
136
92
  },
137
- { adapterVersion: '0.4.8' },
138
93
  );
139
94
 
140
95
  assert.equal(entry.supportStatus, 'supported');
141
- assert.equal(entry.adapterVersion, '0.4.8');
96
+ assert.equal(entry.requiresAdHocResign, true);
97
+ assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
142
98
  assert.equal(entry.cursorVersion, '3.4');
143
- assert.equal(entry.structureFamily, 'mac-agent-D-workbench-U0');
144
- assert.equal(entry.patchTargets?.map((target) => target.name).join(','), 'agent-exec,workbench');
145
- });
146
-
147
- test('default compatibility manifest does not match Cursor 3.4.20 from the v0.5 adapter', () => {
148
- assert.throws(
149
- () =>
150
- resolveCompatEntry(
151
- {
152
- appPath: '/Applications/Cursor.app',
153
- version: '3.4.20',
154
- commit: '0cf8b06883f54e26bb4f0fb8647c9500ccb43310',
155
- },
156
- {
157
- platform: 'darwin',
158
- arch: 'arm64',
159
- nodeVersion: process.version,
160
- },
161
- { adapterVersion: '0.5.8' },
162
- ),
163
- /No compatibility entry for Cursor 3\.4\.20/,
99
+ assert.equal(entry.cursorCommit, '*');
100
+ assert.equal(entry.expectedSha256, '*');
101
+ assert.equal(
102
+ DEFAULT_COMPAT_ENTRIES.some(
103
+ (candidate) =>
104
+ candidate.platform === 'darwin' &&
105
+ candidate.arch === 'arm64' &&
106
+ candidate.cursorVersion === '3.4' &&
107
+ candidate.cursorCommit === '*',
108
+ ),
109
+ true,
164
110
  );
165
111
  });
166
112
 
167
- test('default compatibility manifest supports Cursor 3.6.31 on macOS arm64 with the v0.5 adapter', () => {
113
+ test('default compatibility manifest accepts later Cursor 3.6 patch versions on macOS arm64', () => {
168
114
  const entry = resolveCompatEntry(
169
115
  {
170
- appPath: '/Applications/Cursor.app',
116
+ appPath: '/Users/example/Desktop/Cursor-3.6.31.app',
171
117
  version: '3.6.31',
172
118
  commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
173
119
  },
@@ -176,20 +122,18 @@ test('default compatibility manifest supports Cursor 3.6.31 on macOS arm64 with
176
122
  arch: 'arm64',
177
123
  nodeVersion: process.version,
178
124
  },
179
- { adapterVersion: '0.5.8' },
180
125
  );
181
126
 
182
127
  assert.equal(entry.supportStatus, 'supported');
183
- assert.equal(entry.adapterVersion, '0.5.8');
184
128
  assert.equal(entry.cursorVersion, '3.6');
185
- assert.equal(entry.structureFamily, 'mac-agent-c-workbench-h-uv');
186
- assert.equal(entry.patchTargets?.map((target) => target.name).join(','), 'agent-exec,workbench');
129
+ assert.equal(entry.cursorCommit, '*');
130
+ assert.equal(entry.expectedSha256, '*');
187
131
  });
188
132
 
189
- test('default compatibility manifest supports Cursor 3.7.12 on macOS arm64 with the v0.6 adapter', () => {
133
+ test('default compatibility manifest supports the Cursor 3.7 macOS arm64 version family', () => {
190
134
  const entry = resolveCompatEntry(
191
135
  {
192
- appPath: '/Applications/Cursor.app',
136
+ appPath: '/Users/example/Desktop/Cursor-3.7.12.app',
193
137
  version: '3.7.12',
194
138
  commit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
195
139
  },
@@ -198,52 +142,38 @@ test('default compatibility manifest supports Cursor 3.7.12 on macOS arm64 with
198
142
  arch: 'arm64',
199
143
  nodeVersion: process.version,
200
144
  },
201
- { adapterVersion: '0.6.0' },
202
145
  );
203
146
 
204
147
  assert.equal(entry.supportStatus, 'supported');
205
- assert.equal(entry.adapterVersion, '0.6.0');
148
+ assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
206
149
  assert.equal(entry.cursorVersion, '3.7');
207
- assert.equal(entry.structureFamily, 'mac-3.7-agent-Et-workbench-wv');
208
- assert.equal(entry.patchTargets?.map((target) => target.name).join(','), 'agent-exec,workbench');
150
+ assert.equal(entry.cursorCommit, '*');
151
+ assert.equal(entry.expectedSha256, '*');
209
152
  });
210
153
 
211
- test('default compatibility manifest does not match Cursor 3.7.12 from the v0.5 adapter', () => {
212
- assert.throws(
213
- () =>
214
- resolveCompatEntry(
215
- {
216
- appPath: '/Applications/Cursor.app',
217
- version: '3.7.12',
218
- commit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
219
- },
220
- {
221
- platform: 'darwin',
222
- arch: 'arm64',
223
- nodeVersion: process.version,
224
- },
225
- { adapterVersion: '0.5.8' },
226
- ),
227
- /No compatibility entry for Cursor 3\.7\.12/,
154
+ test('default compatibility manifest supports Cursor 3.6.31 Linux x64 AppImage', () => {
155
+ const entry = resolveCompatEntry(
156
+ {
157
+ appPath: '/home/xubuntu/.cursor-pool/appimages/Cursor-89aa899ccc46fb58/squashfs-root',
158
+ version: '3.6.31',
159
+ commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
160
+ },
161
+ {
162
+ platform: 'linux',
163
+ arch: 'x64',
164
+ nodeVersion: process.version,
165
+ },
228
166
  );
229
- });
230
167
 
231
- test('default compatibility manifest does not claim unverified Linux Cursor packages as supported', () => {
232
- assert.throws(
233
- () =>
234
- resolveCompatEntry(
235
- {
236
- appPath: '/home/xubuntu/.cursor-pool/appimages/Cursor-89aa899ccc46fb58/squashfs-root',
237
- version: '3.6.31',
238
- commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
239
- },
240
- {
241
- platform: 'linux',
242
- arch: 'x64',
243
- nodeVersion: process.version,
244
- },
245
- ),
246
- /No compatibility entry for Cursor 3\.6\.31/,
168
+ assert.equal(entry.supportStatus, 'supported');
169
+ assert.equal(entry.requiresAdHocResign, false);
170
+ assert.equal(
171
+ entry.targetRelativePath,
172
+ 'usr/share/cursor/resources/app/extensions/cursor-agent-exec/dist/main.js',
173
+ );
174
+ assert.equal(
175
+ entry.expectedSha256,
176
+ '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
247
177
  );
248
178
  });
249
179
 
@@ -263,12 +193,10 @@ test('default compatibility manifest supports Cursor 3.5.38 on macOS x64 for Ros
263
193
 
264
194
  assert.equal(entry.supportStatus, 'supported');
265
195
  assert.equal(entry.requiresAdHocResign, true);
266
- assert.equal(entry.cursorVersion, '3.5');
267
196
  assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
268
- assert.equal(
269
- entry.expectedSha256,
270
- 'cb18f0237278884a39e2ce2b8664255e12689ad0803c20096c38e86c36acc51f',
271
- );
197
+ assert.equal(entry.cursorVersion, '3.5');
198
+ assert.equal(entry.cursorCommit, '*');
199
+ assert.equal(entry.expectedSha256, '*');
272
200
  });
273
201
 
274
202
  test('verifies a remote compatibility manifest envelope with the development signature', () => {
@@ -317,8 +245,7 @@ test('loads remote compatibility entries from api base url when signature is val
317
245
  },
318
246
  });
319
247
 
320
- assert.equal(entries[0]?.cursorVersion, '3.7');
321
- assert.equal(entries[0]?.verifiedCursorVersion, '3.7.0');
248
+ assert.equal(entries[0]?.cursorVersion, '3.7.0');
322
249
  });
323
250
 
324
251
  test('loads compatibility entries from a local file URL for disposable client validation', async () => {
@@ -362,66 +289,3 @@ test('falls back to injected compatibility entries before fetching remote manife
362
289
 
363
290
  assert.equal(entries, injected);
364
291
  });
365
-
366
- test('resolveCompatEntry only matches the current adapter version when provided', () => {
367
- const cursor = {
368
- appPath: '/Applications/Cursor.app',
369
- version: '3.7.12',
370
- commit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
371
- };
372
- const environment = {
373
- platform: 'darwin' as const,
374
- arch: 'arm64',
375
- nodeVersion: process.version,
376
- };
377
- const matchingRule = remoteRuleFor(cursor.version, cursor.commit);
378
- const otherAdapterRule = {
379
- ...matchingRule,
380
- adapterVersion: '0.6.0',
381
- userMessage: 'Cursor 3.7.12 needs the 0.6 adapter.',
382
- };
383
-
384
- assert.throws(
385
- () =>
386
- resolveCompatEntry(cursor, environment, {
387
- entries: [otherAdapterRule],
388
- adapterVersion: '0.5.8',
389
- }),
390
- /No compatibility entry for Cursor 3\.7\.12/,
391
- );
392
-
393
- const resolved = resolveCompatEntry(cursor, environment, {
394
- entries: [otherAdapterRule],
395
- adapterVersion: '0.6.0',
396
- });
397
- assert.equal(resolved.adapterVersion, '0.6.0');
398
- });
399
-
400
- test('resolveCompatEntry rejects legacy rules without adapterVersion when current adapter is known', () => {
401
- const cursor = {
402
- appPath: '/Applications/Cursor.app',
403
- version: '3.6.21',
404
- commit: 'e7a7e93f4d75f8272503ecf33cedbaae10114a10',
405
- };
406
- const environment = {
407
- platform: 'darwin' as const,
408
- arch: 'arm64',
409
- nodeVersion: process.version,
410
- };
411
- const { adapterVersion: _adapterVersion, ...legacyRule } = remoteRuleFor(cursor.version, cursor.commit);
412
-
413
- assert.throws(
414
- () =>
415
- resolveCompatEntry(cursor, environment, {
416
- entries: [legacyRule],
417
- adapterVersion: '0.5.8',
418
- }),
419
- /No compatibility entry for Cursor 3\.6\.21/,
420
- );
421
-
422
- const resolved = resolveCompatEntry(cursor, environment, {
423
- entries: [legacyRule],
424
- });
425
- assert.equal(resolved.cursorVersion, '3.6');
426
- assert.equal(resolved.verifiedCursorVersion, '3.6.21');
427
- });
@@ -13,16 +13,6 @@ import {
13
13
  CURSOR_POOL_PATCH_MARKER,
14
14
  } from '../../patcher/src/marker';
15
15
  import { backupPathForCursorAgentExec } from '../../patcher/src/patchCursorAgentExec';
16
- import { CURSOR_WORKBENCH_RELATIVE_PATH } from '../../patcher/src/patchCursorWorkbenchAuthGate';
17
- import {
18
- CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR,
19
- CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_AUTH_GATE_ANCHOR,
20
- CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_LOGIN_ANCHOR,
21
- CURSOR_WORKBENCH_AGENT_LOOP_RUN_ANCHOR,
22
- CURSOR_WORKBENCH_BUILD_FLAGS_LOCAL_MODE_ANCHOR,
23
- CURSOR_WORKBENCH_COMPOSER_AUTH_GATE_ANCHOR,
24
- CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR,
25
- } from '../../patcher/src/workbenchAuthGateMarker';
26
16
  import type { CompatibilityManifestEntry } from '../../shared/src/manifest';
27
17
  import { getExtensionState } from '../src/extensionBundle';
28
18
  import { getLinkedExtensionState, linkedExtensionPathForDir } from '../src/extensionLink';
@@ -45,70 +35,30 @@ const targetRelativePath =
45
35
  const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
46
36
  const serviceServerPath = resolve(repoRoot, 'packages/service/src/server.ts');
47
37
 
48
- function workbenchFixtureContent() {
49
- const localProviderConfigAnchor =
50
- 'async getLocalAgentProviderConfig(e){const t="[AgentClientService][getLocalAgentProviderConfig]",i=L0.localMode?await this.shellEnvironmentService.getShellEnv():{},r=e?.credentials,s=r?.case==="apiKeyCredentials"?r.value:void 0,o=this.reactiveStorageService.applicationUserPersistentStorage,a=o.useOpenAIKey===!0?this.cursorAuthenticationService.openAIKey()??void 0:void 0,u=xgS({apiKeyCandidates:[{value:s?.apiKey,source:"modelDetails.apiKeyCredentials.apiKey"},{value:a,source:"storage.openAIKey"}],baseUrlCandidates:[{value:s?.baseUrl,source:"modelDetails.apiKeyCredentials.baseUrl"},{value:o.openAIBaseUrl,source:"storage.openAIBaseUrl"}]});return{baseUrl:u.baseUrl,apiKey:u.apiKey}}createDefaultLocalModel(e){return "default"}';
51
- return [
52
- `function composer(){return he(Mt,{${CURSOR_WORKBENCH_COMPOSER_AUTH_GATE_ANCHOR},get children(){return "controls"}})}`,
53
- `async function submit(){${CURSOR_WORKBENCH_COMPOSER_SUBMIT_AUTH_GATE_ANCHOR};return "submitted";}`,
54
- `function agentEditorControls(){const T=()=>{${CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_LOGIN_ANCHOR};return n.handleSubmit()};return he(Mt,{${CURSOR_WORKBENCH_AGENT_EDITOR_SEND_BUTTON_AUTH_GATE_ANCHOR}"controls"}})}`,
55
- `const flags={${CURSOR_WORKBENCH_BUILD_FLAGS_LOCAL_MODE_ANCHOR}}`,
56
- localProviderConfigAnchor,
57
- `async function runAgentLoop(){${CURSOR_WORKBENCH_AGENT_LOOP_RUN_ANCHOR}}`,
58
- `async function agentClientRun(){const g={...p,isRunningInTest:p.isRunningInTest??this.environmentService.enableSmokeTestDriver===!0,clientSupportsInlineImages:!0};${CURSOR_WORKBENCH_AGENT_CLIENT_RUN_LOCAL_MODE_ANCHOR}}`,
59
- ].join(';');
60
- }
61
-
62
38
  async function createFixtureApp(prefix: string) {
63
39
  const tempDir = await mkdtemp(join(tmpdir(), prefix));
64
40
  const appPath = join(tempDir, 'Cursor.app');
65
41
  const targetPath = join(appPath, targetRelativePath);
66
42
  const targetContent = `function main() { return "agent"; }\n${CURSOR_POOL_AGENT_EXEC_PROVIDER_REGISTER_ANCHOR}\nmain();\n`;
67
- const workbenchPath = join(appPath, CURSOR_WORKBENCH_RELATIVE_PATH);
68
- const workbenchContent = workbenchFixtureContent();
69
43
  await mkdir(join(appPath, 'Contents/Resources/app/extensions/cursor-agent-exec/dist'), {
70
44
  recursive: true,
71
45
  });
72
- await mkdir(join(appPath, 'Contents/Resources/app/out/vs/workbench'), {
73
- recursive: true,
74
- });
75
46
  await writeFile(
76
47
  join(appPath, 'Contents/Resources/app/product.json'),
77
48
  JSON.stringify({ version: cursorVersion, commit: cursorCommit }),
78
49
  'utf8',
79
50
  );
80
51
  await writeFile(targetPath, targetContent, 'utf8');
81
- await writeFile(workbenchPath, workbenchContent, 'utf8');
82
52
 
83
53
  const originalHash = createHash('sha256').update(targetContent).digest('hex');
84
- const workbenchOriginalHash = createHash('sha256').update(workbenchContent).digest('hex');
85
54
  const compatEntry: CompatibilityManifestEntry = {
86
55
  platform: process.platform,
87
56
  arch: process.arch,
88
57
  cursorVersion,
89
58
  cursorCommit,
90
59
  supportStatus: 'supported',
91
- takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
92
60
  targetRelativePath,
93
61
  expectedSha256: originalHash,
94
- adapterVersion: '0.5.8',
95
- structureFamily: 'fixture-agent-exec-workbench',
96
- patchTargets: [
97
- {
98
- name: 'agent-exec',
99
- targetRelativePath,
100
- expectedSha256: originalHash,
101
- patchStrategy: 'cursor-agent-exec-snippet',
102
- verifyMarker: 'cursor-pool',
103
- },
104
- {
105
- name: 'workbench',
106
- targetRelativePath: CURSOR_WORKBENCH_RELATIVE_PATH,
107
- expectedSha256: workbenchOriginalHash,
108
- patchStrategy: 'cursor-workbench-auth-gate',
109
- verifyMarker: 'cursor-pool-workbench',
110
- },
111
- ],
112
62
  structureSignature: 'fixture',
113
63
  patchStrategy: 'cursor-agent-exec-snippet',
114
64
  verifyMarker: 'cursor-pool',
@@ -127,9 +77,6 @@ async function createFixtureApp(prefix: string) {
127
77
  targetPath,
128
78
  targetContent,
129
79
  originalHash,
130
- workbenchPath,
131
- workbenchContent,
132
- workbenchOriginalHash,
133
80
  runtimeFile: join(tempDir, 'runtime.json'),
134
81
  backupDir: join(tempDir, 'backups'),
135
82
  compatEntry,