@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/compat.ts
CHANGED
|
@@ -5,171 +5,129 @@ import type {
|
|
|
5
5
|
CompatibilityManifestEntry,
|
|
6
6
|
CompatibilityManifestEnvelope,
|
|
7
7
|
} from '@cursor-pool/shared/manifest';
|
|
8
|
-
import {
|
|
9
|
-
CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
10
|
-
CURSOR_WORKBENCH_RELATIVE_PATH,
|
|
11
|
-
} from '@cursor-pool/patcher';
|
|
8
|
+
import { CURSOR_AGENT_EXEC_RELATIVE_PATH } from '@cursor-pool/patcher';
|
|
12
9
|
import type { CliEnvironment } from './environment';
|
|
13
10
|
import type { CursorInfo } from './cursor';
|
|
14
11
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
{
|
|
18
|
-
name: 'agent-exec',
|
|
19
|
-
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
20
|
-
expectedSha256: agentSha256,
|
|
21
|
-
patchStrategy: 'cursor-agent-exec-snippet',
|
|
22
|
-
verifyMarker: 'cursor-pool',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
name: 'workbench',
|
|
26
|
-
targetRelativePath: CURSOR_WORKBENCH_RELATIVE_PATH,
|
|
27
|
-
expectedSha256: workbenchSha256,
|
|
28
|
-
patchStrategy: 'cursor-workbench-auth-gate',
|
|
29
|
-
verifyMarker: 'cursor-pool-workbench',
|
|
30
|
-
},
|
|
31
|
-
];
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function macCompatEntry(input: {
|
|
35
|
-
arch: 'arm64' | 'x64';
|
|
36
|
-
officialMajorVersion: string;
|
|
37
|
-
verifiedCursorVersion: string;
|
|
38
|
-
cursorVersion: string;
|
|
39
|
-
cursorCommit: string;
|
|
40
|
-
adapterVersion: string;
|
|
41
|
-
structureFamily: string;
|
|
42
|
-
takeoverPlanId: string;
|
|
43
|
-
agentSha256: string;
|
|
44
|
-
workbenchSha256: string;
|
|
45
|
-
userMessage: string;
|
|
46
|
-
}): CompatibilityManifestEntry {
|
|
47
|
-
return {
|
|
12
|
+
export const DEFAULT_COMPAT_ENTRIES: CompatibilityManifestEntry[] = [
|
|
13
|
+
{
|
|
48
14
|
platform: 'darwin',
|
|
49
|
-
arch:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
officialDownloadPlatform: `darwin-${input.arch}`,
|
|
53
|
-
verifiedCursorVersion: input.verifiedCursorVersion,
|
|
54
|
-
cursorVersion: input.officialMajorVersion,
|
|
55
|
-
cursorCommit: input.cursorCommit,
|
|
15
|
+
arch: 'arm64',
|
|
16
|
+
cursorVersion: '3.4',
|
|
17
|
+
cursorCommit: '*',
|
|
56
18
|
supportStatus: 'supported',
|
|
57
|
-
adapterVersion: input.adapterVersion,
|
|
58
|
-
takeoverPlanId: input.takeoverPlanId,
|
|
59
|
-
structureFamily: input.structureFamily,
|
|
60
|
-
patchTargets: macPatchTargets(input.agentSha256, input.workbenchSha256),
|
|
61
19
|
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
62
|
-
expectedSha256:
|
|
63
|
-
structureSignature:
|
|
20
|
+
expectedSha256: '*',
|
|
21
|
+
structureSignature: 'ep1-cursor-3-4-family',
|
|
64
22
|
patchStrategy: 'cursor-agent-exec-snippet',
|
|
65
23
|
verifyMarker: 'cursor-pool',
|
|
66
24
|
restoreStrategy: 'external-backup',
|
|
67
|
-
minCliVersion: '0.5.
|
|
68
|
-
minExtensionVersion: '0.5.
|
|
69
|
-
minServiceVersion: '0.5.
|
|
25
|
+
minCliVersion: '0.5.9',
|
|
26
|
+
minExtensionVersion: '0.5.9',
|
|
27
|
+
minServiceVersion: '0.5.9',
|
|
70
28
|
requiresWritableAppBundle: true,
|
|
71
29
|
requiresAdHocResign: true,
|
|
72
|
-
userMessage:
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
export const DEFAULT_COMPAT_ENTRIES: CompatibilityManifestEntry[] = [
|
|
77
|
-
macCompatEntry({
|
|
78
|
-
arch: 'arm64',
|
|
79
|
-
officialMajorVersion: '3.4',
|
|
80
|
-
verifiedCursorVersion: '3.4.20',
|
|
81
|
-
cursorVersion: '3.4.20',
|
|
82
|
-
cursorCommit: '0cf8b06883f54e26bb4f0fb8647c9500ccb43310',
|
|
83
|
-
adapterVersion: '0.4.8',
|
|
84
|
-
structureFamily: 'mac-agent-D-workbench-U0',
|
|
85
|
-
takeoverPlanId: 'cursor-3.4-mac-agent-d-workbench-u0',
|
|
86
|
-
agentSha256: 'c63ae78a3b72df82db224839d552b1f8ca38011e45a37a55ae4ccd75fcdc125f',
|
|
87
|
-
workbenchSha256: '01a7005df6a76159b4edafee3c4a233003626e082212f9d042a81239a2bde388',
|
|
88
|
-
userMessage: 'Cursor 3.4.20 macOS arm64 is supported by the v0.4 adapter.',
|
|
89
|
-
}),
|
|
90
|
-
macCompatEntry({
|
|
91
|
-
arch: 'x64',
|
|
92
|
-
officialMajorVersion: '3.4',
|
|
93
|
-
verifiedCursorVersion: '3.4.20',
|
|
94
|
-
cursorVersion: '3.4.20',
|
|
95
|
-
cursorCommit: '0cf8b06883f54e26bb4f0fb8647c9500ccb43310',
|
|
96
|
-
adapterVersion: '0.4.8',
|
|
97
|
-
structureFamily: 'mac-agent-D-workbench-U0',
|
|
98
|
-
takeoverPlanId: 'cursor-3.4-mac-agent-d-workbench-u0',
|
|
99
|
-
agentSha256: 'c63ae78a3b72df82db224839d552b1f8ca38011e45a37a55ae4ccd75fcdc125f',
|
|
100
|
-
workbenchSha256: '01a7005df6a76159b4edafee3c4a233003626e082212f9d042a81239a2bde388',
|
|
101
|
-
userMessage: 'Cursor 3.4.20 macOS x64 is supported by the v0.4 adapter.',
|
|
102
|
-
}),
|
|
103
|
-
macCompatEntry({
|
|
30
|
+
userMessage: 'Cursor 3.4.x is supported for MVP-0.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
platform: 'darwin',
|
|
104
34
|
arch: 'arm64',
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
35
|
+
cursorVersion: '3.5',
|
|
36
|
+
cursorCommit: '*',
|
|
37
|
+
supportStatus: 'supported',
|
|
38
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
39
|
+
expectedSha256: '*',
|
|
40
|
+
structureSignature: 'ep1-cursor-3-5-family',
|
|
41
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
42
|
+
verifyMarker: 'cursor-pool',
|
|
43
|
+
restoreStrategy: 'external-backup',
|
|
44
|
+
minCliVersion: '0.5.9',
|
|
45
|
+
minExtensionVersion: '0.5.9',
|
|
46
|
+
minServiceVersion: '0.5.9',
|
|
47
|
+
requiresWritableAppBundle: true,
|
|
48
|
+
requiresAdHocResign: true,
|
|
49
|
+
userMessage: 'Cursor 3.5.x is supported for MVP-0.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
platform: 'darwin',
|
|
117
53
|
arch: 'x64',
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
54
|
+
cursorVersion: '3.5',
|
|
55
|
+
cursorCommit: '*',
|
|
56
|
+
supportStatus: 'supported',
|
|
57
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
58
|
+
expectedSha256: '*',
|
|
59
|
+
structureSignature: 'ep1-cursor-3-5-family',
|
|
60
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
61
|
+
verifyMarker: 'cursor-pool',
|
|
62
|
+
restoreStrategy: 'external-backup',
|
|
63
|
+
minCliVersion: '0.5.9',
|
|
64
|
+
minExtensionVersion: '0.5.9',
|
|
65
|
+
minServiceVersion: '0.5.9',
|
|
66
|
+
requiresWritableAppBundle: true,
|
|
67
|
+
requiresAdHocResign: true,
|
|
68
|
+
userMessage: 'Cursor 3.5.x is supported for MVP-0 under Rosetta-launched installers.',
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
platform: 'darwin',
|
|
130
72
|
arch: 'arm64',
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
73
|
+
cursorVersion: '3.6',
|
|
74
|
+
cursorCommit: '*',
|
|
75
|
+
supportStatus: 'supported',
|
|
76
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
77
|
+
expectedSha256: '*',
|
|
78
|
+
structureSignature: 'ep1-cursor-3-6-family',
|
|
79
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
80
|
+
verifyMarker: 'cursor-pool',
|
|
81
|
+
restoreStrategy: 'external-backup',
|
|
82
|
+
minCliVersion: '0.5.9',
|
|
83
|
+
minExtensionVersion: '0.5.9',
|
|
84
|
+
minServiceVersion: '0.5.9',
|
|
85
|
+
requiresWritableAppBundle: true,
|
|
86
|
+
requiresAdHocResign: true,
|
|
87
|
+
userMessage: 'Cursor 3.6.x is supported for MVP-0.',
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
platform: 'darwin',
|
|
143
91
|
arch: 'arm64',
|
|
144
|
-
|
|
145
|
-
|
|
92
|
+
cursorVersion: '3.7',
|
|
93
|
+
cursorCommit: '*',
|
|
94
|
+
supportStatus: 'supported',
|
|
95
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
96
|
+
expectedSha256: '*',
|
|
97
|
+
structureSignature: 'ep1-cursor-3-7-family',
|
|
98
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
99
|
+
verifyMarker: 'cursor-pool',
|
|
100
|
+
restoreStrategy: 'external-backup',
|
|
101
|
+
minCliVersion: '0.5.9',
|
|
102
|
+
minExtensionVersion: '0.5.9',
|
|
103
|
+
minServiceVersion: '0.5.9',
|
|
104
|
+
requiresWritableAppBundle: true,
|
|
105
|
+
requiresAdHocResign: true,
|
|
106
|
+
userMessage: 'Cursor 3.7.x is supported for MVP-0.',
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
platform: 'linux',
|
|
110
|
+
arch: 'x64',
|
|
146
111
|
cursorVersion: '3.6.31',
|
|
147
112
|
cursorCommit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
structureFamily: 'mac-3.7-agent-Et-workbench-wv',
|
|
163
|
-
takeoverPlanId: 'cursor-3.7-mac-agent-et-workbench-wv',
|
|
164
|
-
agentSha256: '9ce7a2f40a98a27eb1b609a79e0e1707bad5fbb02493693f6f18945a7640dde4',
|
|
165
|
-
workbenchSha256: 'e91aa502a84d5b1653a2c1f3a71a2d4160ab5f1de5809dd230756ecc0cc27db9',
|
|
166
|
-
userMessage: 'Cursor 3.7.12 macOS arm64 is supported by the v0.6 adapter.',
|
|
167
|
-
}),
|
|
113
|
+
supportStatus: 'supported',
|
|
114
|
+
targetRelativePath: 'usr/share/cursor/resources/app/extensions/cursor-agent-exec/dist/main.js',
|
|
115
|
+
expectedSha256: '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
|
|
116
|
+
structureSignature: 'linux-appimage-3-6-31-cursor-agent-exec',
|
|
117
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
118
|
+
verifyMarker: 'cursor-pool',
|
|
119
|
+
restoreStrategy: 'external-backup',
|
|
120
|
+
minCliVersion: '0.5.7',
|
|
121
|
+
minExtensionVersion: '0.5.7',
|
|
122
|
+
minServiceVersion: '0.5.7',
|
|
123
|
+
requiresWritableAppBundle: true,
|
|
124
|
+
requiresAdHocResign: false,
|
|
125
|
+
userMessage: 'Cursor 3.6.31 Linux x64 AppImage is supported.',
|
|
126
|
+
},
|
|
168
127
|
];
|
|
169
128
|
|
|
170
129
|
export type ResolveCompatOptions = {
|
|
171
130
|
entries?: CompatibilityManifestEntry[];
|
|
172
|
-
adapterVersion?: string;
|
|
173
131
|
};
|
|
174
132
|
|
|
175
133
|
export type CompatManifestFetchResponse = {
|
|
@@ -220,34 +178,6 @@ function asBoolean(value: unknown, field: string) {
|
|
|
220
178
|
return value;
|
|
221
179
|
}
|
|
222
180
|
|
|
223
|
-
function asOptionalString(value: unknown, field: string) {
|
|
224
|
-
if (value === undefined) {
|
|
225
|
-
return undefined;
|
|
226
|
-
}
|
|
227
|
-
return asString(value, field);
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
function normalizePatchTargets(value: unknown) {
|
|
231
|
-
if (value === undefined) {
|
|
232
|
-
return undefined;
|
|
233
|
-
}
|
|
234
|
-
if (!Array.isArray(value)) {
|
|
235
|
-
throw new Error('compat manifest patchTargets invalid');
|
|
236
|
-
}
|
|
237
|
-
return value.map((target) => {
|
|
238
|
-
if (!isRecord(target)) {
|
|
239
|
-
throw new Error('compat manifest patchTarget invalid');
|
|
240
|
-
}
|
|
241
|
-
return {
|
|
242
|
-
name: asString(target.name, 'patchTargets.name'),
|
|
243
|
-
targetRelativePath: asString(target.targetRelativePath, 'patchTargets.targetRelativePath'),
|
|
244
|
-
expectedSha256: asString(target.expectedSha256, 'patchTargets.expectedSha256'),
|
|
245
|
-
patchStrategy: asString(target.patchStrategy, 'patchTargets.patchStrategy'),
|
|
246
|
-
verifyMarker: asString(target.verifyMarker, 'patchTargets.verifyMarker'),
|
|
247
|
-
};
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
181
|
function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
252
182
|
if (!isRecord(value)) {
|
|
253
183
|
throw new Error('compat manifest rule invalid');
|
|
@@ -263,23 +193,12 @@ function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
|
263
193
|
) {
|
|
264
194
|
throw new Error('compat manifest revision invalid');
|
|
265
195
|
}
|
|
266
|
-
const adapterVersion = asOptionalString(value.adapterVersion, 'adapterVersion');
|
|
267
|
-
const structureFamily = asOptionalString(value.structureFamily, 'structureFamily');
|
|
268
|
-
const patchTargets = normalizePatchTargets(value.patchTargets);
|
|
269
196
|
return {
|
|
270
197
|
platform: asString(value.platform, 'platform'),
|
|
271
198
|
arch: asString(value.arch, 'arch'),
|
|
272
|
-
...(value.officialSourceUrl === undefined ? {} : { officialSourceUrl: asString(value.officialSourceUrl, 'officialSourceUrl') }),
|
|
273
|
-
...(value.officialDownloadUrl === undefined ? {} : { officialDownloadUrl: asString(value.officialDownloadUrl, 'officialDownloadUrl') }),
|
|
274
|
-
...(value.officialDownloadPlatform === undefined ? {} : { officialDownloadPlatform: asString(value.officialDownloadPlatform, 'officialDownloadPlatform') }),
|
|
275
|
-
...(value.verifiedCursorVersion === undefined ? {} : { verifiedCursorVersion: asString(value.verifiedCursorVersion, 'verifiedCursorVersion') }),
|
|
276
199
|
cursorVersion: asString(value.cursorVersion, 'cursorVersion'),
|
|
277
200
|
cursorCommit: asString(value.cursorCommit, 'cursorCommit'),
|
|
278
201
|
supportStatus,
|
|
279
|
-
...(adapterVersion === undefined ? {} : { adapterVersion }),
|
|
280
|
-
takeoverPlanId: asString(value.takeoverPlanId, 'takeoverPlanId'),
|
|
281
|
-
...(structureFamily === undefined ? {} : { structureFamily }),
|
|
282
|
-
...(patchTargets === undefined ? {} : { patchTargets }),
|
|
283
202
|
targetRelativePath: asString(value.targetRelativePath, 'targetRelativePath'),
|
|
284
203
|
expectedSha256: asString(value.expectedSha256, 'expectedSha256'),
|
|
285
204
|
structureSignature: asString(value.structureSignature, 'structureSignature'),
|
|
@@ -301,10 +220,8 @@ function canonicalRuleSegment(rule: RemoteCompatibilityManifestRule) {
|
|
|
301
220
|
rule.platform,
|
|
302
221
|
rule.arch,
|
|
303
222
|
rule.cursorVersion,
|
|
304
|
-
rule.verifiedCursorVersion ?? '',
|
|
305
223
|
rule.cursorCommit,
|
|
306
224
|
rule.supportStatus,
|
|
307
|
-
rule.takeoverPlanId,
|
|
308
225
|
String(rule.revision ?? 1),
|
|
309
226
|
].join(':');
|
|
310
227
|
}
|
|
@@ -318,6 +235,27 @@ function safeEqualHex(left: string, right: string) {
|
|
|
318
235
|
return timingSafeEqual(leftBuffer, rightBuffer);
|
|
319
236
|
}
|
|
320
237
|
|
|
238
|
+
function cursorVersionFamily(version: string) {
|
|
239
|
+
const match = version.match(/^(\d+\.\d+)(?:\.|$)/);
|
|
240
|
+
return match?.[1];
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function compatEntryMatches(
|
|
244
|
+
candidate: CompatibilityManifestEntry,
|
|
245
|
+
cursor: CursorInfo,
|
|
246
|
+
environment: CliEnvironment,
|
|
247
|
+
) {
|
|
248
|
+
if (candidate.platform !== environment.platform || candidate.arch !== environment.arch) {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
const versionMatches =
|
|
252
|
+
candidate.cursorVersion === cursor.version ||
|
|
253
|
+
candidate.cursorVersion === cursorVersionFamily(cursor.version);
|
|
254
|
+
const commitMatches =
|
|
255
|
+
candidate.cursorCommit === '*' || candidate.cursorCommit === cursor.commit;
|
|
256
|
+
return versionMatches && commitMatches;
|
|
257
|
+
}
|
|
258
|
+
|
|
321
259
|
export function buildCompatManifestSignature(
|
|
322
260
|
version: number,
|
|
323
261
|
rules: RemoteCompatibilityManifestRule[],
|
|
@@ -356,11 +294,6 @@ export function verifyCompatManifestEnvelope(
|
|
|
356
294
|
return rules.map(({ revision, ...rule }) => rule);
|
|
357
295
|
}
|
|
358
296
|
|
|
359
|
-
function officialCursorMajorVersion(cursorVersion: string) {
|
|
360
|
-
const match = cursorVersion.match(/^(\d+\.\d+)(?:\.|$)/);
|
|
361
|
-
return match?.[1] ?? cursorVersion;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
297
|
export function compatManifestUrlFromApiBaseUrl(apiBaseUrl: string) {
|
|
365
298
|
return `${apiBaseUrl.replace(/\/+$/, '')}/api/client/compatibility/manifest`;
|
|
366
299
|
}
|
|
@@ -407,12 +340,7 @@ export function resolveCompatEntry(
|
|
|
407
340
|
) {
|
|
408
341
|
const entries = options.entries ?? DEFAULT_COMPAT_ENTRIES;
|
|
409
342
|
const entry = entries.find(
|
|
410
|
-
(candidate) =>
|
|
411
|
-
candidate.platform === environment.platform &&
|
|
412
|
-
candidate.arch === environment.arch &&
|
|
413
|
-
candidate.cursorVersion === officialCursorMajorVersion(cursor.version) &&
|
|
414
|
-
candidate.cursorCommit === cursor.commit &&
|
|
415
|
-
(!options.adapterVersion || candidate.adapterVersion === options.adapterVersion),
|
|
343
|
+
(candidate) => compatEntryMatches(candidate, cursor, environment),
|
|
416
344
|
);
|
|
417
345
|
|
|
418
346
|
if (!entry) {
|
package/src/extensionBundle.ts
CHANGED
|
@@ -55,7 +55,7 @@ async function exists(path: string) {
|
|
|
55
55
|
function buildRuntimeManifest(sourceManifest: Record<string, unknown>) {
|
|
56
56
|
return {
|
|
57
57
|
name: 'cursorpool',
|
|
58
|
-
version: typeof sourceManifest.version === 'string' ? sourceManifest.version : '0.5.
|
|
58
|
+
version: typeof sourceManifest.version === 'string' ? sourceManifest.version : '0.5.9',
|
|
59
59
|
displayName: 'Cursor Pool 平台模式',
|
|
60
60
|
publisher: 'cursor-pool',
|
|
61
61
|
type: sourceManifest.type,
|
package/src/extensionLink.ts
CHANGED
|
@@ -4,8 +4,7 @@ import { basename, dirname, join, resolve } from 'node:path';
|
|
|
4
4
|
import { resolveExtensionInstallPath } from './extensionBundle';
|
|
5
5
|
import type { ExtensionState } from './trial';
|
|
6
6
|
|
|
7
|
-
export const LINKED_EXTENSION_DIRNAME = 'cursor-pool.extension-0.5.
|
|
8
|
-
const LINKED_EXTENSION_DIRNAME_PREFIX = 'cursor-pool.extension-';
|
|
7
|
+
export const LINKED_EXTENSION_DIRNAME = 'cursor-pool.extension-0.5.9';
|
|
9
8
|
const RUNTIME_EXTENSION_ID = 'cursor-pool.cursorpool';
|
|
10
9
|
const STALE_EXTENSION_IDS = new Set([
|
|
11
10
|
RUNTIME_EXTENSION_ID,
|
|
@@ -49,17 +48,10 @@ async function readRuntimeManifest(linkedPath: string) {
|
|
|
49
48
|
};
|
|
50
49
|
const publisher = typeof manifest.publisher === 'string' ? manifest.publisher : 'cursor-pool';
|
|
51
50
|
const name = typeof manifest.name === 'string' ? manifest.name : 'cursorpool';
|
|
52
|
-
const version = typeof manifest.version === 'string' ? manifest.version : '0.5.
|
|
51
|
+
const version = typeof manifest.version === 'string' ? manifest.version : '0.5.9';
|
|
53
52
|
return { id: `${publisher}.${name}`, version };
|
|
54
53
|
}
|
|
55
54
|
|
|
56
|
-
function linkedExtensionDirnameForVersion(version: string) {
|
|
57
|
-
if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(version)) {
|
|
58
|
-
throw new Error(`Unsafe extension version: ${version}`);
|
|
59
|
-
}
|
|
60
|
-
return `${LINKED_EXTENSION_DIRNAME_PREFIX}${version}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
55
|
export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string, linkedPath: string) {
|
|
64
56
|
const indexPath = join(resolveExtensionInstallPath(cursorExtensionsDir), 'extensions.json');
|
|
65
57
|
if (!(await exists(indexPath))) {
|
|
@@ -71,13 +63,11 @@ export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string,
|
|
|
71
63
|
relativeLocation?: string;
|
|
72
64
|
}>;
|
|
73
65
|
const manifest = await readRuntimeManifest(linkedPath);
|
|
74
|
-
const relativeLocation = basename(linkedPath);
|
|
75
66
|
const nextEntries = entries.filter((entry) => {
|
|
76
67
|
const id = entry.identifier?.id;
|
|
77
|
-
const relativeLocation = entry.relativeLocation ?? '';
|
|
78
68
|
return (
|
|
79
69
|
!STALE_EXTENSION_IDS.has(id ?? '') &&
|
|
80
|
-
|
|
70
|
+
entry.relativeLocation !== LINKED_EXTENSION_DIRNAME &&
|
|
81
71
|
entry.relativeLocation !== 'keg1255.cursorpool-1.0.52'
|
|
82
72
|
);
|
|
83
73
|
});
|
|
@@ -89,7 +79,7 @@ export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string,
|
|
|
89
79
|
path: linkedPath,
|
|
90
80
|
scheme: 'file',
|
|
91
81
|
},
|
|
92
|
-
relativeLocation,
|
|
82
|
+
relativeLocation: LINKED_EXTENSION_DIRNAME,
|
|
93
83
|
version: manifest.version,
|
|
94
84
|
});
|
|
95
85
|
await writeFile(indexPath, `${JSON.stringify(nextEntries, null, 2)}\n`, 'utf8');
|
|
@@ -102,23 +92,15 @@ function assertSafeLinkedExtensionPath(linkedPath: string) {
|
|
|
102
92
|
(segment) => segment === 'extensions' || segment === 'Extensions',
|
|
103
93
|
);
|
|
104
94
|
|
|
105
|
-
if (
|
|
95
|
+
if (basename(resolvedLinkedPath) !== LINKED_EXTENSION_DIRNAME || !hasExtensionsParent) {
|
|
106
96
|
throw new Error(
|
|
107
|
-
`Unsafe linked extension path for recursive removal: ${linkedPath}. Expected an extensions/${
|
|
97
|
+
`Unsafe linked extension path for recursive removal: ${linkedPath}. Expected an extensions/${LINKED_EXTENSION_DIRNAME} bundle path.`,
|
|
108
98
|
);
|
|
109
99
|
}
|
|
110
100
|
}
|
|
111
101
|
|
|
112
102
|
export function linkedExtensionPathForDir(cursorExtensionsDir: string) {
|
|
113
|
-
return join(resolveExtensionInstallPath(cursorExtensionsDir), LINKED_EXTENSION_DIRNAME);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export async function linkedExtensionPathForSource(cursorExtensionsDir: string, sourceBundlePath: string) {
|
|
117
|
-
const manifest = await readRuntimeManifest(sourceBundlePath);
|
|
118
|
-
return join(
|
|
119
|
-
resolveExtensionInstallPath(cursorExtensionsDir),
|
|
120
|
-
linkedExtensionDirnameForVersion(manifest.version),
|
|
121
|
-
);
|
|
103
|
+
return join(resolve(resolveExtensionInstallPath(cursorExtensionsDir)), LINKED_EXTENSION_DIRNAME);
|
|
122
104
|
}
|
|
123
105
|
|
|
124
106
|
export async function getLinkedExtensionState(linkedPath: string | undefined): Promise<LinkedExtensionState> {
|
|
@@ -137,10 +119,7 @@ export async function linkExtensionBundle({
|
|
|
137
119
|
cursorExtensionsDir,
|
|
138
120
|
}: LinkExtensionBundleOptions): Promise<LinkExtensionBundleResult> {
|
|
139
121
|
const resolvedSourceBundlePath = resolveExtensionInstallPath(sourceBundlePath);
|
|
140
|
-
const linkedPath =
|
|
141
|
-
(await getLinkedExtensionState(resolvedSourceBundlePath)) === 'missing'
|
|
142
|
-
? linkedExtensionPathForDir(cursorExtensionsDir)
|
|
143
|
-
: await linkedExtensionPathForSource(cursorExtensionsDir, resolvedSourceBundlePath);
|
|
122
|
+
const linkedPath = linkedExtensionPathForDir(cursorExtensionsDir);
|
|
144
123
|
|
|
145
124
|
if ((await getLinkedExtensionState(resolvedSourceBundlePath)) === 'missing') {
|
|
146
125
|
return { state: 'missing', linkedPath };
|
package/src/install.ts
CHANGED
|
@@ -7,18 +7,16 @@ import {
|
|
|
7
7
|
restoreCursorAgentExec,
|
|
8
8
|
restoreCursorAlwaysLocal,
|
|
9
9
|
restoreCursorWorkbenchAuthGate,
|
|
10
|
-
containsCursorWorkbenchAuthGateMarker,
|
|
11
10
|
} from '@cursor-pool/patcher';
|
|
12
11
|
import { sha256File } from '@cursor-pool/patcher/hash';
|
|
13
12
|
import { startServer } from '@cursor-pool/service';
|
|
14
|
-
import { assertBundledTakeoverPlan } from '@cursor-pool/takeover-plans';
|
|
15
13
|
import {
|
|
16
14
|
readRuntimeInfo,
|
|
17
15
|
resolveRuntimeFile,
|
|
18
16
|
writeRuntimeInfo,
|
|
19
17
|
type RuntimeInfo,
|
|
20
18
|
} from '@cursor-pool/service';
|
|
21
|
-
import type { CompatibilityManifestEntry
|
|
19
|
+
import type { CompatibilityManifestEntry } from '@cursor-pool/shared/manifest';
|
|
22
20
|
import { DEFAULT_RUNTIME_FILE } from '@cursor-pool/shared/runtime';
|
|
23
21
|
import { writeClientConfig } from '@cursor-pool/shared/clientConfig';
|
|
24
22
|
import { containsCursorPoolMarker } from '@cursor-pool/patcher/marker';
|
|
@@ -34,7 +32,6 @@ import {
|
|
|
34
32
|
import {
|
|
35
33
|
getLinkedExtensionState,
|
|
36
34
|
linkExtensionBundle,
|
|
37
|
-
linkedExtensionPathForSource,
|
|
38
35
|
linkedExtensionPathForDir,
|
|
39
36
|
refreshCursorExtensionsIndex,
|
|
40
37
|
removeLinkedExtensionBundle,
|
|
@@ -107,7 +104,7 @@ export type InstallOptions = FindCursorOptions &
|
|
|
107
104
|
};
|
|
108
105
|
|
|
109
106
|
const REAL_CURSOR_EXTENSIONS_DIR = '~/.cursor/extensions';
|
|
110
|
-
const PACKAGE_VERSION = '0.5.
|
|
107
|
+
const PACKAGE_VERSION = '0.5.9';
|
|
111
108
|
const AUTOSTART_SERVICE_STARTUP_TIMEOUT_MS = 30_000;
|
|
112
109
|
|
|
113
110
|
function delay(ms: number) {
|
|
@@ -133,57 +130,17 @@ async function maybeAdHocResign({
|
|
|
133
130
|
return 'ad-hoc' as const;
|
|
134
131
|
}
|
|
135
132
|
|
|
136
|
-
function
|
|
137
|
-
if (target.name === 'workbench' || target.verifyMarker === 'cursor-pool-workbench') {
|
|
138
|
-
return containsCursorWorkbenchAuthGateMarker;
|
|
139
|
-
}
|
|
140
|
-
return containsCursorPoolMarker;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async function assertExpectedHash(
|
|
144
|
-
targetPath: string,
|
|
145
|
-
expectedSha256: string,
|
|
146
|
-
containsExpectedMarker = containsCursorPoolMarker,
|
|
147
|
-
) {
|
|
133
|
+
async function assertExpectedHash(targetPath: string, expectedSha256: string) {
|
|
148
134
|
const currentHash = await sha256File(targetPath);
|
|
149
135
|
if (currentHash !== expectedSha256) {
|
|
150
136
|
const content = await readFile(targetPath, 'utf8');
|
|
151
|
-
if (
|
|
137
|
+
if (containsCursorPoolMarker(content)) {
|
|
152
138
|
return;
|
|
153
139
|
}
|
|
154
140
|
throw new Error(`Patch target hash mismatch: expected ${expectedSha256}, got ${currentHash}`);
|
|
155
141
|
}
|
|
156
142
|
}
|
|
157
143
|
|
|
158
|
-
function compatPatchTargets(compat: CompatibilityManifestEntry): CompatibilityPatchTarget[] {
|
|
159
|
-
if (compat.patchTargets?.length) {
|
|
160
|
-
return compat.patchTargets;
|
|
161
|
-
}
|
|
162
|
-
return [
|
|
163
|
-
{
|
|
164
|
-
name: 'agent-exec',
|
|
165
|
-
targetRelativePath: compat.targetRelativePath,
|
|
166
|
-
expectedSha256: compat.expectedSha256,
|
|
167
|
-
patchStrategy: compat.patchStrategy,
|
|
168
|
-
verifyMarker: compat.verifyMarker,
|
|
169
|
-
},
|
|
170
|
-
];
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
function workbenchTargetRelativePathFromCompat(compat: CompatibilityManifestEntry) {
|
|
174
|
-
return compat.patchTargets?.find((target) => target.name === 'workbench')?.targetRelativePath;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
async function assertExpectedPatchTargetHashes(appPath: string, compat: CompatibilityManifestEntry) {
|
|
178
|
-
for (const target of compatPatchTargets(compat)) {
|
|
179
|
-
await assertExpectedHash(
|
|
180
|
-
join(appPath, target.targetRelativePath),
|
|
181
|
-
target.expectedSha256,
|
|
182
|
-
markerPredicateForPatchTarget(target),
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
144
|
async function startServiceFromAutostart(options: InstallOptions, targetMode: 'real' | 'disposable') {
|
|
188
145
|
const autostart = await installAutostart(options, targetMode);
|
|
189
146
|
const runtimeFile = options.runtimeFile ?? DEFAULT_RUNTIME_FILE;
|
|
@@ -418,12 +375,11 @@ async function linkInstallExtensionBundle({
|
|
|
418
375
|
sourceBundlePath: string;
|
|
419
376
|
cursorExtensionsDir: string;
|
|
420
377
|
}): ReturnType<typeof linkExtensionBundle> {
|
|
378
|
+
const linkedPath = linkedExtensionPathForDir(cursorExtensionsDir);
|
|
421
379
|
if ((await getLinkedExtensionState(sourceBundlePath)) === 'missing') {
|
|
422
|
-
const linkedPath = linkedExtensionPathForDir(cursorExtensionsDir);
|
|
423
380
|
return { state: 'missing', linkedPath };
|
|
424
381
|
}
|
|
425
382
|
|
|
426
|
-
const linkedPath = await linkedExtensionPathForSource(cursorExtensionsDir, sourceBundlePath);
|
|
427
383
|
await removeInstallLinkedExtensionBundle(linkedPath, cursorExtensionsDir);
|
|
428
384
|
await mkdir(dirname(linkedPath), { recursive: true });
|
|
429
385
|
await cp(sourceBundlePath, linkedPath, { recursive: true });
|
|
@@ -447,19 +403,15 @@ export async function install(options: InstallOptions = {}) {
|
|
|
447
403
|
compatManifestUrl: options.compatManifestUrl,
|
|
448
404
|
fetchManifest: options.fetchCompatManifest,
|
|
449
405
|
});
|
|
450
|
-
const
|
|
451
|
-
? undefined
|
|
452
|
-
: PACKAGE_VERSION.split('-', 1)[0].split('+', 1)[0];
|
|
453
|
-
const compat = resolveCompatEntry(cursor, environment, { entries: compatEntries, adapterVersion });
|
|
454
|
-
assertBundledTakeoverPlan(compat.takeoverPlanId);
|
|
455
|
-
const workbenchTargetRelativePath = workbenchTargetRelativePathFromCompat(compat);
|
|
406
|
+
const compat = resolveCompatEntry(cursor, environment, { entries: compatEntries });
|
|
456
407
|
const targetPath = join(cursor.appPath, compat.targetRelativePath);
|
|
457
408
|
const originalSha256 = await sha256File(targetPath);
|
|
458
|
-
|
|
409
|
+
if (compat.expectedSha256 !== '*') {
|
|
410
|
+
await assertExpectedHash(targetPath, compat.expectedSha256);
|
|
411
|
+
}
|
|
459
412
|
const patchSetBeforeInstall = await readCursorPatchSetState(cursor.appPath, {
|
|
460
413
|
agentExecTargetRelativePath: compat.targetRelativePath,
|
|
461
414
|
platform: environment.platform,
|
|
462
|
-
workbenchTargetRelativePath,
|
|
463
415
|
});
|
|
464
416
|
const wasPatchedBeforeInstall = patchSetBeforeInstall.allApplied;
|
|
465
417
|
const existingTrialRecord = await readTrialRecord(cursor.appPath, {
|
|
@@ -551,7 +503,6 @@ export async function install(options: InstallOptions = {}) {
|
|
|
551
503
|
backupDir: options.backupDir,
|
|
552
504
|
platform: environment.platform,
|
|
553
505
|
agentExecTargetRelativePath: compat.targetRelativePath,
|
|
554
|
-
workbenchTargetRelativePath,
|
|
555
506
|
patchCursorAgentExec: options.patchCursorAgentExec,
|
|
556
507
|
patchCursorWorkbenchAuthGate: options.patchCursorWorkbenchAuthGate,
|
|
557
508
|
});
|
|
@@ -581,7 +532,6 @@ export async function install(options: InstallOptions = {}) {
|
|
|
581
532
|
appPath: cursor.appPath,
|
|
582
533
|
cursorVersion: cursor.version,
|
|
583
534
|
cursorCommit: cursor.commit,
|
|
584
|
-
takeoverPlanId: compat.takeoverPlanId,
|
|
585
535
|
targetRelativePath: compat.targetRelativePath,
|
|
586
536
|
originalSha256,
|
|
587
537
|
compatSupportStatus: compat.supportStatus,
|
|
@@ -626,7 +576,6 @@ export async function install(options: InstallOptions = {}) {
|
|
|
626
576
|
`mode: ${target.mode}`,
|
|
627
577
|
`app: ${cursor.appPath}`,
|
|
628
578
|
`compat: ${compat.supportStatus}`,
|
|
629
|
-
`takeover-plan: ${compat.takeoverPlanId}`,
|
|
630
579
|
`extension: ${extension.state}`,
|
|
631
580
|
`service: running ${service.host}:${service.port}`,
|
|
632
581
|
`autostart: ${autostartState}`,
|
|
@@ -646,7 +595,6 @@ export async function install(options: InstallOptions = {}) {
|
|
|
646
595
|
(await readCursorPatchSetState(cursor.appPath, {
|
|
647
596
|
agentExecTargetRelativePath: compat.targetRelativePath,
|
|
648
597
|
platform: environment.platform,
|
|
649
|
-
workbenchTargetRelativePath,
|
|
650
598
|
})).appliedCount > 0);
|
|
651
599
|
} catch (rollbackError) {
|
|
652
600
|
rollbackErrors.push(rollbackError);
|
|
@@ -656,7 +604,6 @@ export async function install(options: InstallOptions = {}) {
|
|
|
656
604
|
await restoreCursorSet(cursor.appPath, {
|
|
657
605
|
backupDir: options.backupDir,
|
|
658
606
|
platform: environment.platform,
|
|
659
|
-
workbenchTargetRelativePath,
|
|
660
607
|
restoreCursorAgentExec: options.restoreCursorAgentExec,
|
|
661
608
|
restoreCursorAlwaysLocal: options.restoreCursorAlwaysLocal,
|
|
662
609
|
restoreCursorWorkbenchAuthGate: options.restoreCursorWorkbenchAuthGate,
|