@cursorpool-dev/cli 0.5.8 → 0.5.10
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 +102 -19
- package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +88 -13
- package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +162 -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 +201 -194
- package/src/cursor.ts +45 -4
- package/src/extensionBundle.ts +1 -1
- package/src/extensionLink.ts +8 -29
- package/src/install.ts +10 -62
- package/src/installRecord.ts +0 -2
- package/src/patchSet.ts +49 -13
- package/src/platform.ts +3 -3
- package/src/repair.ts +9 -13
- package/src/restore.ts +11 -12
- package/src/status.ts +5 -9
- package/src/target.ts +12 -0
- package/src/trial.ts +2 -3
- package/src/uninstall.ts +6 -2
- package/test/compat.test.ts +146 -192
- package/test/cursor.test.ts +54 -0
- package/test/e2e-install.test.ts +29 -46
- package/test/extensionLink.test.ts +26 -49
- package/test/install.test.ts +4 -64
- package/test/patchSet.test.ts +71 -0
- package/test/repair.test.ts +131 -1
- package/test/restore.test.ts +59 -3
- package/test/status.test.ts +0 -1
- package/test/target.test.ts +28 -0
- 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/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,166 +63,208 @@ 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
|
-
|
|
104
|
-
|
|
105
|
-
|
|
81
|
+
test('default compatibility manifest supports the Cursor 3.4 macOS arm64 version family', () => {
|
|
82
|
+
const entry = resolveCompatEntry(
|
|
83
|
+
{
|
|
84
|
+
appPath: '/Users/example/Desktop/Cursor-3.4.0.app',
|
|
85
|
+
version: '3.4.0',
|
|
86
|
+
commit: 'cursor-3-4-family-commit',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
platform: 'darwin',
|
|
90
|
+
arch: 'arm64',
|
|
91
|
+
nodeVersion: process.version,
|
|
92
|
+
},
|
|
106
93
|
);
|
|
94
|
+
|
|
95
|
+
assert.equal(entry.supportStatus, 'supported');
|
|
96
|
+
assert.equal(entry.requiresAdHocResign, true);
|
|
97
|
+
assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
|
|
98
|
+
assert.equal(entry.cursorVersion, '3.4');
|
|
99
|
+
assert.equal(entry.cursorCommit, '*');
|
|
100
|
+
assert.equal(entry.expectedSha256, '*');
|
|
107
101
|
assert.equal(
|
|
108
|
-
DEFAULT_COMPAT_ENTRIES.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
102
|
+
DEFAULT_COMPAT_ENTRIES.some(
|
|
103
|
+
(candidate) =>
|
|
104
|
+
candidate.platform === 'darwin' &&
|
|
105
|
+
candidate.arch === 'arm64' &&
|
|
106
|
+
candidate.cursorVersion === '3.4' &&
|
|
107
|
+
candidate.cursorCommit === '*',
|
|
112
108
|
),
|
|
113
109
|
true,
|
|
114
110
|
);
|
|
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
111
|
});
|
|
124
112
|
|
|
125
|
-
test('default compatibility manifest
|
|
113
|
+
test('default compatibility manifest accepts later Cursor 3.6 patch versions on macOS arm64', () => {
|
|
126
114
|
const entry = resolveCompatEntry(
|
|
127
115
|
{
|
|
128
|
-
appPath: '/
|
|
129
|
-
version: '3.
|
|
130
|
-
commit: '
|
|
116
|
+
appPath: '/Users/example/Desktop/Cursor-3.6.31.app',
|
|
117
|
+
version: '3.6.31',
|
|
118
|
+
commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
131
119
|
},
|
|
132
120
|
{
|
|
133
121
|
platform: 'darwin',
|
|
134
122
|
arch: 'arm64',
|
|
135
123
|
nodeVersion: process.version,
|
|
136
124
|
},
|
|
137
|
-
{ adapterVersion: '0.4.8' },
|
|
138
125
|
);
|
|
139
126
|
|
|
140
127
|
assert.equal(entry.supportStatus, 'supported');
|
|
141
|
-
assert.equal(entry.
|
|
142
|
-
assert.equal(entry.
|
|
143
|
-
assert.equal(entry.
|
|
144
|
-
assert.equal(entry.patchTargets?.map((target) => target.name).join(','), 'agent-exec,workbench');
|
|
128
|
+
assert.equal(entry.cursorVersion, '3.6');
|
|
129
|
+
assert.equal(entry.cursorCommit, '*');
|
|
130
|
+
assert.equal(entry.expectedSha256, '*');
|
|
145
131
|
});
|
|
146
132
|
|
|
147
|
-
test('default compatibility manifest
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
nodeVersion: process.version,
|
|
160
|
-
},
|
|
161
|
-
{ adapterVersion: '0.5.8' },
|
|
162
|
-
),
|
|
163
|
-
/No compatibility entry for Cursor 3\.4\.20/,
|
|
133
|
+
test('default compatibility manifest supports the Cursor 3.7 macOS arm64 version family', () => {
|
|
134
|
+
const entry = resolveCompatEntry(
|
|
135
|
+
{
|
|
136
|
+
appPath: '/Users/example/Desktop/Cursor-3.7.12.app',
|
|
137
|
+
version: '3.7.12',
|
|
138
|
+
commit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
platform: 'darwin',
|
|
142
|
+
arch: 'arm64',
|
|
143
|
+
nodeVersion: process.version,
|
|
144
|
+
},
|
|
164
145
|
);
|
|
146
|
+
|
|
147
|
+
assert.equal(entry.supportStatus, 'supported');
|
|
148
|
+
assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
|
|
149
|
+
assert.equal(entry.cursorVersion, '3.7');
|
|
150
|
+
assert.equal(entry.cursorCommit, '*');
|
|
151
|
+
assert.equal(entry.expectedSha256, '*');
|
|
165
152
|
});
|
|
166
153
|
|
|
167
|
-
test('default compatibility manifest supports Cursor 3.6.31
|
|
154
|
+
test('default compatibility manifest supports Cursor 3.6.31 Linux x64 AppImage', () => {
|
|
168
155
|
const entry = resolveCompatEntry(
|
|
169
156
|
{
|
|
170
|
-
appPath: '/
|
|
157
|
+
appPath: '/home/xubuntu/.cursor-pool/appimages/Cursor-89aa899ccc46fb58/squashfs-root',
|
|
171
158
|
version: '3.6.31',
|
|
172
159
|
commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
173
160
|
},
|
|
174
161
|
{
|
|
175
|
-
platform: '
|
|
176
|
-
arch: '
|
|
162
|
+
platform: 'linux',
|
|
163
|
+
arch: 'x64',
|
|
177
164
|
nodeVersion: process.version,
|
|
178
165
|
},
|
|
179
|
-
{ adapterVersion: '0.5.8' },
|
|
180
166
|
);
|
|
181
167
|
|
|
182
168
|
assert.equal(entry.supportStatus, 'supported');
|
|
183
|
-
assert.equal(entry.
|
|
184
|
-
assert.equal(
|
|
185
|
-
|
|
186
|
-
|
|
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',
|
|
177
|
+
);
|
|
187
178
|
});
|
|
188
179
|
|
|
189
|
-
test('default compatibility manifest supports Cursor 3.7.12
|
|
180
|
+
test('default compatibility manifest supports Cursor 3.7.12 Linux arm64 deb installs', () => {
|
|
190
181
|
const entry = resolveCompatEntry(
|
|
191
182
|
{
|
|
192
|
-
appPath: '/
|
|
183
|
+
appPath: '/usr/share/cursor',
|
|
193
184
|
version: '3.7.12',
|
|
194
185
|
commit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
|
|
195
186
|
},
|
|
196
187
|
{
|
|
197
|
-
platform: '
|
|
188
|
+
platform: 'linux',
|
|
198
189
|
arch: 'arm64',
|
|
199
190
|
nodeVersion: process.version,
|
|
200
191
|
},
|
|
201
|
-
{ adapterVersion: '0.6.0' },
|
|
202
192
|
);
|
|
203
193
|
|
|
204
194
|
assert.equal(entry.supportStatus, 'supported');
|
|
205
|
-
assert.equal(entry.
|
|
206
|
-
assert.equal(
|
|
207
|
-
|
|
208
|
-
|
|
195
|
+
assert.equal(entry.requiresAdHocResign, false);
|
|
196
|
+
assert.equal(
|
|
197
|
+
entry.targetRelativePath,
|
|
198
|
+
'resources/app/extensions/cursor-agent-exec/dist/main.js',
|
|
199
|
+
);
|
|
200
|
+
assert.equal(
|
|
201
|
+
entry.expectedSha256,
|
|
202
|
+
'9ce7a2f40a98a27eb1b609a79e0e1707bad5fbb02493693f6f18945a7640dde4',
|
|
203
|
+
);
|
|
209
204
|
});
|
|
210
205
|
|
|
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/,
|
|
206
|
+
test('default compatibility manifest supports verified Cursor 3.4 Linux arm64 deb installs', () => {
|
|
207
|
+
const entry = resolveCompatEntry(
|
|
208
|
+
{
|
|
209
|
+
appPath: '/usr/share/cursor',
|
|
210
|
+
version: '3.4.20',
|
|
211
|
+
commit: '0cf8b06883f54e26bb4f0fb8647c9500ccb43310',
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
platform: 'linux',
|
|
215
|
+
arch: 'arm64',
|
|
216
|
+
nodeVersion: process.version,
|
|
217
|
+
},
|
|
228
218
|
);
|
|
229
|
-
});
|
|
230
219
|
|
|
231
|
-
|
|
232
|
-
assert.
|
|
233
|
-
|
|
234
|
-
|
|
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/,
|
|
220
|
+
assert.equal(entry.supportStatus, 'supported');
|
|
221
|
+
assert.equal(entry.requiresAdHocResign, false);
|
|
222
|
+
assert.equal(
|
|
223
|
+
entry.targetRelativePath,
|
|
224
|
+
'resources/app/extensions/cursor-agent-exec/dist/main.js',
|
|
247
225
|
);
|
|
226
|
+
assert.equal(
|
|
227
|
+
entry.expectedSha256,
|
|
228
|
+
'4ccb7526e5ece8f6a98a99724a048977698cbf52cb2033ec06f2b5a0a085fe71',
|
|
229
|
+
);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('default compatibility manifest supports verified Cursor 3.5 and 3.6 Linux arm64 deb installs', () => {
|
|
233
|
+
const cases = [
|
|
234
|
+
{
|
|
235
|
+
version: '3.5.38',
|
|
236
|
+
commit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
237
|
+
expectedSha256: 'cb18f0237278884a39e2ce2b8664255e12689ad0803c20096c38e86c36acc51f',
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
version: '3.6.31',
|
|
241
|
+
commit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
242
|
+
expectedSha256: '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
|
|
243
|
+
},
|
|
244
|
+
];
|
|
245
|
+
|
|
246
|
+
for (const fixture of cases) {
|
|
247
|
+
const entry = resolveCompatEntry(
|
|
248
|
+
{
|
|
249
|
+
appPath: '/usr/share/cursor',
|
|
250
|
+
version: fixture.version,
|
|
251
|
+
commit: fixture.commit,
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
platform: 'linux',
|
|
255
|
+
arch: 'arm64',
|
|
256
|
+
nodeVersion: process.version,
|
|
257
|
+
},
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
assert.equal(entry.supportStatus, 'supported');
|
|
261
|
+
assert.equal(entry.requiresAdHocResign, false);
|
|
262
|
+
assert.equal(
|
|
263
|
+
entry.targetRelativePath,
|
|
264
|
+
'resources/app/extensions/cursor-agent-exec/dist/main.js',
|
|
265
|
+
);
|
|
266
|
+
assert.equal(entry.expectedSha256, fixture.expectedSha256);
|
|
267
|
+
}
|
|
248
268
|
});
|
|
249
269
|
|
|
250
270
|
test('default compatibility manifest supports Cursor 3.5.38 on macOS x64 for Rosetta-launched installers', () => {
|
|
@@ -263,12 +283,10 @@ test('default compatibility manifest supports Cursor 3.5.38 on macOS x64 for Ros
|
|
|
263
283
|
|
|
264
284
|
assert.equal(entry.supportStatus, 'supported');
|
|
265
285
|
assert.equal(entry.requiresAdHocResign, true);
|
|
266
|
-
assert.equal(entry.cursorVersion, '3.5');
|
|
267
286
|
assert.equal(entry.targetRelativePath, CURSOR_AGENT_EXEC_RELATIVE_PATH);
|
|
268
|
-
assert.equal(
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
);
|
|
287
|
+
assert.equal(entry.cursorVersion, '3.5');
|
|
288
|
+
assert.equal(entry.cursorCommit, '*');
|
|
289
|
+
assert.equal(entry.expectedSha256, '*');
|
|
272
290
|
});
|
|
273
291
|
|
|
274
292
|
test('verifies a remote compatibility manifest envelope with the development signature', () => {
|
|
@@ -317,8 +335,7 @@ test('loads remote compatibility entries from api base url when signature is val
|
|
|
317
335
|
},
|
|
318
336
|
});
|
|
319
337
|
|
|
320
|
-
assert.equal(entries[0]?.cursorVersion, '3.7');
|
|
321
|
-
assert.equal(entries[0]?.verifiedCursorVersion, '3.7.0');
|
|
338
|
+
assert.equal(entries[0]?.cursorVersion, '3.7.0');
|
|
322
339
|
});
|
|
323
340
|
|
|
324
341
|
test('loads compatibility entries from a local file URL for disposable client validation', async () => {
|
|
@@ -362,66 +379,3 @@ test('falls back to injected compatibility entries before fetching remote manife
|
|
|
362
379
|
|
|
363
380
|
assert.equal(entries, injected);
|
|
364
381
|
});
|
|
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/cursor.test.ts
CHANGED
|
@@ -22,6 +22,60 @@ test('defaultCursorAppPath gives a helpful Windows error when LOCALAPPDATA is un
|
|
|
22
22
|
);
|
|
23
23
|
});
|
|
24
24
|
|
|
25
|
+
test('defaultCursorAppPath auto-detects Linux deb installs from the cursor launcher on PATH', () => {
|
|
26
|
+
assert.equal(
|
|
27
|
+
defaultCursorAppPath({
|
|
28
|
+
platform: 'linux',
|
|
29
|
+
execFileSync: (command, args) => {
|
|
30
|
+
if (command === 'which' && args[0] === 'cursor') {
|
|
31
|
+
return '/usr/bin/cursor\n';
|
|
32
|
+
}
|
|
33
|
+
if (command === 'readlink' && args.join(' ') === '-f /usr/bin/cursor') {
|
|
34
|
+
return '/usr/share/cursor/bin/cursor\n';
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`unexpected command: ${command} ${args.join(' ')}`);
|
|
37
|
+
},
|
|
38
|
+
}),
|
|
39
|
+
'/usr/share/cursor',
|
|
40
|
+
);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('findCursor auto-detects Linux deb installs from the cursor launcher on PATH', async () => {
|
|
44
|
+
const tempDir = await mkdtemp(join(tmpdir(), 'cursor-pool-linux-deb-'));
|
|
45
|
+
const appPath = join(tempDir, 'usr/share/cursor');
|
|
46
|
+
const launcherPath = join(appPath, 'bin/cursor');
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
await mkdir(join(appPath, 'resources/app'), { recursive: true });
|
|
50
|
+
await mkdir(join(appPath, 'bin'), { recursive: true });
|
|
51
|
+
await writeFile(launcherPath, '#!/bin/sh\n', 'utf8');
|
|
52
|
+
await writeFile(
|
|
53
|
+
join(appPath, 'resources/app/product.json'),
|
|
54
|
+
JSON.stringify({ version: '3.7.12', commit: 'linux-arm64-commit' }),
|
|
55
|
+
'utf8',
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const cursor = await findCursor({
|
|
59
|
+
platform: 'linux',
|
|
60
|
+
execFile: async (command, args) => {
|
|
61
|
+
if (command === 'which' && args[0] === 'cursor') {
|
|
62
|
+
return { stdout: '/usr/bin/cursor\n' };
|
|
63
|
+
}
|
|
64
|
+
if (command === 'readlink' && args.join(' ') === '-f /usr/bin/cursor') {
|
|
65
|
+
return { stdout: `${launcherPath}\n` };
|
|
66
|
+
}
|
|
67
|
+
throw new Error(`unexpected command: ${command} ${args.join(' ')}`);
|
|
68
|
+
},
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
assert.equal(cursor.appPath, appPath);
|
|
72
|
+
assert.equal(cursor.version, '3.7.12');
|
|
73
|
+
assert.equal(cursor.commit, 'linux-arm64-commit');
|
|
74
|
+
} finally {
|
|
75
|
+
await rm(tempDir, { recursive: true, force: true });
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
25
79
|
test('findCursor extracts Linux AppImage files before reading product metadata', async () => {
|
|
26
80
|
const tempDir = await mkdtemp(join(tmpdir(), 'cursor-pool-linux-appimage-'));
|
|
27
81
|
const appImagePath = join(tempDir, 'Cursor.AppImage');
|
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';
|
|
@@ -42,20 +32,32 @@ const cursorVersion = '3.5.38';
|
|
|
42
32
|
const cursorCommit = '009bb5a3600dd98fe1c1f25798f767f686e14750';
|
|
43
33
|
const targetRelativePath =
|
|
44
34
|
'Contents/Resources/app/extensions/cursor-agent-exec/dist/main.js';
|
|
35
|
+
const alwaysLocalRelativePath =
|
|
36
|
+
'Contents/Resources/app/extensions/cursor-always-local/dist/main.js';
|
|
37
|
+
const workbenchRelativePath =
|
|
38
|
+
'Contents/Resources/app/out/vs/workbench/workbench.desktop.main.js';
|
|
45
39
|
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
|
|
46
40
|
const serviceServerPath = resolve(repoRoot, 'packages/service/src/server.ts');
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
41
|
+
const composerAuthGateAnchor =
|
|
42
|
+
'get when(){return p()&&!fzC},get fallback(){return he(DGC,{})}';
|
|
43
|
+
const composerSubmitAuthGateAnchor =
|
|
44
|
+
'if(!p()){e.cursorAuthenticationService.login(),e.commandService.executeCommand(wV,"general");return}';
|
|
45
|
+
const agentLoopRunAnchor =
|
|
46
|
+
'await this.agentClientService.run(te,H,$e,Ne,Ce,T,ze,me,we,[],ct)';
|
|
47
|
+
const buildFlagsLocalModeAnchor = 'localMode:!1';
|
|
48
|
+
const localProviderConfigAnchor =
|
|
49
|
+
'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"}';
|
|
50
|
+
const agentClientRunLocalModeAnchor =
|
|
51
|
+
'if(L0.localMode){try{g.onNetworkPhaseStart?.()}catch(b){this.logService.warn("[AgentClientService] onNetworkPhaseStart callback failed in local mode",b)}return this.runLocalAgentInExtensionHost(e,t,i,r,s,a,d,h,g)}return this.client.run(e,t,i,r,s,o,a,u,d,h,g)';
|
|
52
|
+
|
|
53
|
+
function workbenchFixture() {
|
|
51
54
|
return [
|
|
52
|
-
`function composer(){return he(Mt,{${
|
|
53
|
-
`async function submit(){${
|
|
54
|
-
`
|
|
55
|
-
`const flags={${CURSOR_WORKBENCH_BUILD_FLAGS_LOCAL_MODE_ANCHOR}}`,
|
|
55
|
+
`function composer(){return he(Mt,{${composerAuthGateAnchor},get children(){return "controls"}})}`,
|
|
56
|
+
`async function submit(){${composerSubmitAuthGateAnchor};return "submitted";}`,
|
|
57
|
+
`const flags={${buildFlagsLocalModeAnchor}}`,
|
|
56
58
|
localProviderConfigAnchor,
|
|
57
|
-
`async function runAgentLoop(){${
|
|
58
|
-
`async function agentClientRun(){const g={
|
|
59
|
+
`async function runAgentLoop(){${agentLoopRunAnchor}}`,
|
|
60
|
+
`async function agentClientRun(){const g={};${agentClientRunLocalModeAnchor}}`,
|
|
59
61
|
].join(';');
|
|
60
62
|
}
|
|
61
63
|
|
|
@@ -63,12 +65,15 @@ async function createFixtureApp(prefix: string) {
|
|
|
63
65
|
const tempDir = await mkdtemp(join(tmpdir(), prefix));
|
|
64
66
|
const appPath = join(tempDir, 'Cursor.app');
|
|
65
67
|
const targetPath = join(appPath, targetRelativePath);
|
|
68
|
+
const alwaysLocalPath = join(appPath, alwaysLocalRelativePath);
|
|
69
|
+
const workbenchPath = join(appPath, workbenchRelativePath);
|
|
66
70
|
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
71
|
await mkdir(join(appPath, 'Contents/Resources/app/extensions/cursor-agent-exec/dist'), {
|
|
70
72
|
recursive: true,
|
|
71
73
|
});
|
|
74
|
+
await mkdir(join(appPath, 'Contents/Resources/app/extensions/cursor-always-local/dist'), {
|
|
75
|
+
recursive: true,
|
|
76
|
+
});
|
|
72
77
|
await mkdir(join(appPath, 'Contents/Resources/app/out/vs/workbench'), {
|
|
73
78
|
recursive: true,
|
|
74
79
|
});
|
|
@@ -78,37 +83,18 @@ async function createFixtureApp(prefix: string) {
|
|
|
78
83
|
'utf8',
|
|
79
84
|
);
|
|
80
85
|
await writeFile(targetPath, targetContent, 'utf8');
|
|
81
|
-
await writeFile(
|
|
86
|
+
await writeFile(alwaysLocalPath, 'function alwaysLocal(){}\n', 'utf8');
|
|
87
|
+
await writeFile(workbenchPath, workbenchFixture(), 'utf8');
|
|
82
88
|
|
|
83
89
|
const originalHash = createHash('sha256').update(targetContent).digest('hex');
|
|
84
|
-
const workbenchOriginalHash = createHash('sha256').update(workbenchContent).digest('hex');
|
|
85
90
|
const compatEntry: CompatibilityManifestEntry = {
|
|
86
91
|
platform: process.platform,
|
|
87
92
|
arch: process.arch,
|
|
88
93
|
cursorVersion,
|
|
89
94
|
cursorCommit,
|
|
90
95
|
supportStatus: 'supported',
|
|
91
|
-
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
92
96
|
targetRelativePath,
|
|
93
97
|
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
98
|
structureSignature: 'fixture',
|
|
113
99
|
patchStrategy: 'cursor-agent-exec-snippet',
|
|
114
100
|
verifyMarker: 'cursor-pool',
|
|
@@ -127,9 +113,6 @@ async function createFixtureApp(prefix: string) {
|
|
|
127
113
|
targetPath,
|
|
128
114
|
targetContent,
|
|
129
115
|
originalHash,
|
|
130
|
-
workbenchPath,
|
|
131
|
-
workbenchContent,
|
|
132
|
-
workbenchOriginalHash,
|
|
133
116
|
runtimeFile: join(tempDir, 'runtime.json'),
|
|
134
117
|
backupDir: join(tempDir, 'backups'),
|
|
135
118
|
compatEntry,
|