@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.
- package/node_modules/@cursor-pool/extension/dist/extension.js +46 -116
- package/node_modules/@cursor-pool/extension/package.json +3 -3
- package/node_modules/@cursor-pool/extension/src/api.ts +2 -17
- package/node_modules/@cursor-pool/extension/src/panel.ts +3 -26
- package/node_modules/@cursor-pool/extension/test/panel.test.ts +1 -34
- package/node_modules/@cursor-pool/patcher/package.json +2 -2
- package/node_modules/@cursor-pool/patcher/src/marker.ts +72 -7
- package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +80 -17
- package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
- package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +151 -149
- package/node_modules/@cursor-pool/service/package.json +2 -2
- package/node_modules/@cursor-pool/service/src/platformSession.ts +7 -30
- package/node_modules/@cursor-pool/service/src/server.ts +1 -1
- package/node_modules/@cursor-pool/service/test/platformSession.test.ts +4 -5
- package/node_modules/@cursor-pool/service/test/server.test.ts +1 -130
- package/node_modules/@cursor-pool/shared/package.json +1 -1
- package/node_modules/@cursor-pool/shared/src/manifest.ts +0 -35
- package/node_modules/@cursor-pool/shared/test/manifest.test.ts +9 -43
- package/package.json +5 -7
- package/src/compat.ts +124 -196
- package/src/extensionBundle.ts +1 -1
- package/src/extensionLink.ts +8 -29
- package/src/install.ts +9 -62
- package/src/installRecord.ts +0 -2
- package/src/patchSet.ts +6 -12
- package/src/platform.ts +3 -3
- package/src/repair.ts +2 -10
- package/src/restore.ts +4 -12
- package/src/status.ts +0 -6
- package/src/trial.ts +2 -3
- package/test/compat.test.ts +59 -195
- package/test/e2e-install.test.ts +0 -53
- package/test/extensionLink.test.ts +26 -49
- package/test/install.test.ts +4 -64
- package/test/repair.test.ts +0 -1
- package/test/status.test.ts +0 -1
- package/test/trial.test.ts +15 -1
- package/node_modules/@cursor-pool/takeover-plans/package.json +0 -12
- package/node_modules/@cursor-pool/takeover-plans/src/index.ts +0 -22
- package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +0 -37
- package/node_modules/@cursor-pool/takeover-plans/src/types.ts +0 -9
- package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +0 -23
package/src/installRecord.ts
CHANGED
|
@@ -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
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
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.
|
|
86
|
-
serviceVersion: '0.5.
|
|
87
|
-
extensionVersion: '0.5.
|
|
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.
|
|
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
|
|
135
|
+
const result = await restoreCursorAgentExec(cursor.appPath, {
|
|
141
136
|
backupDir,
|
|
142
|
-
|
|
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: ${
|
|
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) {
|
package/test/compat.test.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
|
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
|
-
|
|
90
|
-
|
|
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 === '
|
|
75
|
+
candidate.cursorCommit === '*',
|
|
97
76
|
),
|
|
98
77
|
true,
|
|
99
78
|
);
|
|
100
79
|
});
|
|
101
80
|
|
|
102
|
-
test('default compatibility
|
|
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: '/
|
|
129
|
-
version: '3.4.
|
|
130
|
-
commit: '
|
|
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.
|
|
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.
|
|
144
|
-
assert.equal(entry.
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
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
|
|
113
|
+
test('default compatibility manifest accepts later Cursor 3.6 patch versions on macOS arm64', () => {
|
|
168
114
|
const entry = resolveCompatEntry(
|
|
169
115
|
{
|
|
170
|
-
appPath: '/
|
|
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.
|
|
186
|
-
assert.equal(entry.
|
|
129
|
+
assert.equal(entry.cursorCommit, '*');
|
|
130
|
+
assert.equal(entry.expectedSha256, '*');
|
|
187
131
|
});
|
|
188
132
|
|
|
189
|
-
test('default compatibility manifest supports Cursor 3.7
|
|
133
|
+
test('default compatibility manifest supports the Cursor 3.7 macOS arm64 version family', () => {
|
|
190
134
|
const entry = resolveCompatEntry(
|
|
191
135
|
{
|
|
192
|
-
appPath: '/
|
|
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.
|
|
148
|
+
assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
|
|
206
149
|
assert.equal(entry.cursorVersion, '3.7');
|
|
207
|
-
assert.equal(entry.
|
|
208
|
-
assert.equal(entry.
|
|
150
|
+
assert.equal(entry.cursorCommit, '*');
|
|
151
|
+
assert.equal(entry.expectedSha256, '*');
|
|
209
152
|
});
|
|
210
153
|
|
|
211
|
-
test('default compatibility manifest
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
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
|
-
|
|
232
|
-
assert.
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
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
|
-
|
|
270
|
-
|
|
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
|
-
});
|
package/test/e2e-install.test.ts
CHANGED
|
@@ -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,
|