@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/src/compat.ts
CHANGED
|
@@ -5,171 +5,208 @@ 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
|
-
}
|
|
12
|
+
const LINUX_DEB_AGENT_EXEC_RELATIVE_PATH =
|
|
13
|
+
'resources/app/extensions/cursor-agent-exec/dist/main.js';
|
|
33
14
|
|
|
34
|
-
|
|
35
|
-
|
|
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 {
|
|
15
|
+
export const DEFAULT_COMPAT_ENTRIES: CompatibilityManifestEntry[] = [
|
|
16
|
+
{
|
|
48
17
|
platform: 'darwin',
|
|
49
|
-
arch:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
officialDownloadPlatform: `darwin-${input.arch}`,
|
|
53
|
-
verifiedCursorVersion: input.verifiedCursorVersion,
|
|
54
|
-
cursorVersion: input.officialMajorVersion,
|
|
55
|
-
cursorCommit: input.cursorCommit,
|
|
18
|
+
arch: 'arm64',
|
|
19
|
+
cursorVersion: '3.4',
|
|
20
|
+
cursorCommit: '*',
|
|
56
21
|
supportStatus: 'supported',
|
|
57
|
-
adapterVersion: input.adapterVersion,
|
|
58
|
-
takeoverPlanId: input.takeoverPlanId,
|
|
59
|
-
structureFamily: input.structureFamily,
|
|
60
|
-
patchTargets: macPatchTargets(input.agentSha256, input.workbenchSha256),
|
|
61
22
|
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
62
|
-
expectedSha256:
|
|
63
|
-
structureSignature:
|
|
23
|
+
expectedSha256: '*',
|
|
24
|
+
structureSignature: 'ep1-cursor-3-4-family',
|
|
64
25
|
patchStrategy: 'cursor-agent-exec-snippet',
|
|
65
26
|
verifyMarker: 'cursor-pool',
|
|
66
27
|
restoreStrategy: 'external-backup',
|
|
67
|
-
minCliVersion: '0.5.
|
|
68
|
-
minExtensionVersion: '0.5.
|
|
69
|
-
minServiceVersion: '0.5.
|
|
28
|
+
minCliVersion: '0.5.10',
|
|
29
|
+
minExtensionVersion: '0.5.10',
|
|
30
|
+
minServiceVersion: '0.5.10',
|
|
70
31
|
requiresWritableAppBundle: true,
|
|
71
32
|
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({
|
|
33
|
+
userMessage: 'Cursor 3.4.x is supported for MVP-0.',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
platform: 'darwin',
|
|
104
37
|
arch: 'arm64',
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
38
|
+
cursorVersion: '3.5',
|
|
39
|
+
cursorCommit: '*',
|
|
40
|
+
supportStatus: 'supported',
|
|
41
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
42
|
+
expectedSha256: '*',
|
|
43
|
+
structureSignature: 'ep1-cursor-3-5-family',
|
|
44
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
45
|
+
verifyMarker: 'cursor-pool',
|
|
46
|
+
restoreStrategy: 'external-backup',
|
|
47
|
+
minCliVersion: '0.5.10',
|
|
48
|
+
minExtensionVersion: '0.5.10',
|
|
49
|
+
minServiceVersion: '0.5.10',
|
|
50
|
+
requiresWritableAppBundle: true,
|
|
51
|
+
requiresAdHocResign: true,
|
|
52
|
+
userMessage: 'Cursor 3.5.x is supported for MVP-0.',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
platform: 'darwin',
|
|
117
56
|
arch: 'x64',
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
57
|
+
cursorVersion: '3.5',
|
|
58
|
+
cursorCommit: '*',
|
|
59
|
+
supportStatus: 'supported',
|
|
60
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
61
|
+
expectedSha256: '*',
|
|
62
|
+
structureSignature: 'ep1-cursor-3-5-family',
|
|
63
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
64
|
+
verifyMarker: 'cursor-pool',
|
|
65
|
+
restoreStrategy: 'external-backup',
|
|
66
|
+
minCliVersion: '0.5.10',
|
|
67
|
+
minExtensionVersion: '0.5.10',
|
|
68
|
+
minServiceVersion: '0.5.10',
|
|
69
|
+
requiresWritableAppBundle: true,
|
|
70
|
+
requiresAdHocResign: true,
|
|
71
|
+
userMessage: 'Cursor 3.5.x is supported for MVP-0 under Rosetta-launched installers.',
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
platform: 'darwin',
|
|
130
75
|
arch: 'arm64',
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
76
|
+
cursorVersion: '3.6',
|
|
77
|
+
cursorCommit: '*',
|
|
78
|
+
supportStatus: 'supported',
|
|
79
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
80
|
+
expectedSha256: '*',
|
|
81
|
+
structureSignature: 'ep1-cursor-3-6-family',
|
|
82
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
83
|
+
verifyMarker: 'cursor-pool',
|
|
84
|
+
restoreStrategy: 'external-backup',
|
|
85
|
+
minCliVersion: '0.5.10',
|
|
86
|
+
minExtensionVersion: '0.5.10',
|
|
87
|
+
minServiceVersion: '0.5.10',
|
|
88
|
+
requiresWritableAppBundle: true,
|
|
89
|
+
requiresAdHocResign: true,
|
|
90
|
+
userMessage: 'Cursor 3.6.x is supported for MVP-0.',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
platform: 'darwin',
|
|
143
94
|
arch: 'arm64',
|
|
144
|
-
|
|
145
|
-
|
|
95
|
+
cursorVersion: '3.7',
|
|
96
|
+
cursorCommit: '*',
|
|
97
|
+
supportStatus: 'supported',
|
|
98
|
+
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
99
|
+
expectedSha256: '*',
|
|
100
|
+
structureSignature: 'ep1-cursor-3-7-family',
|
|
101
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
102
|
+
verifyMarker: 'cursor-pool',
|
|
103
|
+
restoreStrategy: 'external-backup',
|
|
104
|
+
minCliVersion: '0.5.10',
|
|
105
|
+
minExtensionVersion: '0.5.10',
|
|
106
|
+
minServiceVersion: '0.5.10',
|
|
107
|
+
requiresWritableAppBundle: true,
|
|
108
|
+
requiresAdHocResign: true,
|
|
109
|
+
userMessage: 'Cursor 3.7.x is supported for MVP-0.',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
platform: 'linux',
|
|
113
|
+
arch: 'x64',
|
|
146
114
|
cursorVersion: '3.6.31',
|
|
147
115
|
cursorCommit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
116
|
+
supportStatus: 'supported',
|
|
117
|
+
targetRelativePath: 'usr/share/cursor/resources/app/extensions/cursor-agent-exec/dist/main.js',
|
|
118
|
+
expectedSha256: '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
|
|
119
|
+
structureSignature: 'linux-appimage-3-6-31-cursor-agent-exec',
|
|
120
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
121
|
+
verifyMarker: 'cursor-pool',
|
|
122
|
+
restoreStrategy: 'external-backup',
|
|
123
|
+
minCliVersion: '0.5.7',
|
|
124
|
+
minExtensionVersion: '0.5.7',
|
|
125
|
+
minServiceVersion: '0.5.7',
|
|
126
|
+
requiresWritableAppBundle: true,
|
|
127
|
+
requiresAdHocResign: false,
|
|
128
|
+
userMessage: 'Cursor 3.6.31 Linux x64 AppImage is supported.',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
platform: 'linux',
|
|
132
|
+
arch: 'arm64',
|
|
133
|
+
cursorVersion: '3.4',
|
|
134
|
+
cursorCommit: '*',
|
|
135
|
+
supportStatus: 'supported',
|
|
136
|
+
targetRelativePath: LINUX_DEB_AGENT_EXEC_RELATIVE_PATH,
|
|
137
|
+
expectedSha256: '4ccb7526e5ece8f6a98a99724a048977698cbf52cb2033ec06f2b5a0a085fe71',
|
|
138
|
+
structureSignature: 'linux-arm64-deb-cursor-3-4-family',
|
|
139
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
140
|
+
verifyMarker: 'cursor-pool',
|
|
141
|
+
restoreStrategy: 'external-backup',
|
|
142
|
+
minCliVersion: '0.5.10',
|
|
143
|
+
minExtensionVersion: '0.5.10',
|
|
144
|
+
minServiceVersion: '0.5.10',
|
|
145
|
+
requiresWritableAppBundle: true,
|
|
146
|
+
requiresAdHocResign: false,
|
|
147
|
+
userMessage: 'Cursor 3.4.x Linux arm64 deb installs are supported.',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
platform: 'linux',
|
|
156
151
|
arch: 'arm64',
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
152
|
+
cursorVersion: '3.5',
|
|
153
|
+
cursorCommit: '*',
|
|
154
|
+
supportStatus: 'supported',
|
|
155
|
+
targetRelativePath: LINUX_DEB_AGENT_EXEC_RELATIVE_PATH,
|
|
156
|
+
expectedSha256: 'cb18f0237278884a39e2ce2b8664255e12689ad0803c20096c38e86c36acc51f',
|
|
157
|
+
structureSignature: 'linux-arm64-deb-cursor-3-5-family',
|
|
158
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
159
|
+
verifyMarker: 'cursor-pool',
|
|
160
|
+
restoreStrategy: 'external-backup',
|
|
161
|
+
minCliVersion: '0.5.10',
|
|
162
|
+
minExtensionVersion: '0.5.10',
|
|
163
|
+
minServiceVersion: '0.5.10',
|
|
164
|
+
requiresWritableAppBundle: true,
|
|
165
|
+
requiresAdHocResign: false,
|
|
166
|
+
userMessage: 'Cursor 3.5.x Linux arm64 deb installs are supported.',
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
platform: 'linux',
|
|
170
|
+
arch: 'arm64',
|
|
171
|
+
cursorVersion: '3.6',
|
|
172
|
+
cursorCommit: '*',
|
|
173
|
+
supportStatus: 'supported',
|
|
174
|
+
targetRelativePath: LINUX_DEB_AGENT_EXEC_RELATIVE_PATH,
|
|
175
|
+
expectedSha256: '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
|
|
176
|
+
structureSignature: 'linux-arm64-deb-cursor-3-6-family',
|
|
177
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
178
|
+
verifyMarker: 'cursor-pool',
|
|
179
|
+
restoreStrategy: 'external-backup',
|
|
180
|
+
minCliVersion: '0.5.10',
|
|
181
|
+
minExtensionVersion: '0.5.10',
|
|
182
|
+
minServiceVersion: '0.5.10',
|
|
183
|
+
requiresWritableAppBundle: true,
|
|
184
|
+
requiresAdHocResign: false,
|
|
185
|
+
userMessage: 'Cursor 3.6.x Linux arm64 deb installs are supported.',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
platform: 'linux',
|
|
189
|
+
arch: 'arm64',
|
|
190
|
+
cursorVersion: '3.7',
|
|
191
|
+
cursorCommit: '*',
|
|
192
|
+
supportStatus: 'supported',
|
|
193
|
+
targetRelativePath: LINUX_DEB_AGENT_EXEC_RELATIVE_PATH,
|
|
194
|
+
expectedSha256: '9ce7a2f40a98a27eb1b609a79e0e1707bad5fbb02493693f6f18945a7640dde4',
|
|
195
|
+
structureSignature: 'linux-arm64-deb-cursor-3-7-family',
|
|
196
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
197
|
+
verifyMarker: 'cursor-pool',
|
|
198
|
+
restoreStrategy: 'external-backup',
|
|
199
|
+
minCliVersion: '0.5.10',
|
|
200
|
+
minExtensionVersion: '0.5.10',
|
|
201
|
+
minServiceVersion: '0.5.10',
|
|
202
|
+
requiresWritableAppBundle: true,
|
|
203
|
+
requiresAdHocResign: false,
|
|
204
|
+
userMessage: 'Cursor 3.7.x Linux arm64 deb installs are supported.',
|
|
205
|
+
},
|
|
168
206
|
];
|
|
169
207
|
|
|
170
208
|
export type ResolveCompatOptions = {
|
|
171
209
|
entries?: CompatibilityManifestEntry[];
|
|
172
|
-
adapterVersion?: string;
|
|
173
210
|
};
|
|
174
211
|
|
|
175
212
|
export type CompatManifestFetchResponse = {
|
|
@@ -220,34 +257,6 @@ function asBoolean(value: unknown, field: string) {
|
|
|
220
257
|
return value;
|
|
221
258
|
}
|
|
222
259
|
|
|
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
260
|
function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
252
261
|
if (!isRecord(value)) {
|
|
253
262
|
throw new Error('compat manifest rule invalid');
|
|
@@ -263,23 +272,12 @@ function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
|
263
272
|
) {
|
|
264
273
|
throw new Error('compat manifest revision invalid');
|
|
265
274
|
}
|
|
266
|
-
const adapterVersion = asOptionalString(value.adapterVersion, 'adapterVersion');
|
|
267
|
-
const structureFamily = asOptionalString(value.structureFamily, 'structureFamily');
|
|
268
|
-
const patchTargets = normalizePatchTargets(value.patchTargets);
|
|
269
275
|
return {
|
|
270
276
|
platform: asString(value.platform, 'platform'),
|
|
271
277
|
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
278
|
cursorVersion: asString(value.cursorVersion, 'cursorVersion'),
|
|
277
279
|
cursorCommit: asString(value.cursorCommit, 'cursorCommit'),
|
|
278
280
|
supportStatus,
|
|
279
|
-
...(adapterVersion === undefined ? {} : { adapterVersion }),
|
|
280
|
-
takeoverPlanId: asString(value.takeoverPlanId, 'takeoverPlanId'),
|
|
281
|
-
...(structureFamily === undefined ? {} : { structureFamily }),
|
|
282
|
-
...(patchTargets === undefined ? {} : { patchTargets }),
|
|
283
281
|
targetRelativePath: asString(value.targetRelativePath, 'targetRelativePath'),
|
|
284
282
|
expectedSha256: asString(value.expectedSha256, 'expectedSha256'),
|
|
285
283
|
structureSignature: asString(value.structureSignature, 'structureSignature'),
|
|
@@ -301,10 +299,8 @@ function canonicalRuleSegment(rule: RemoteCompatibilityManifestRule) {
|
|
|
301
299
|
rule.platform,
|
|
302
300
|
rule.arch,
|
|
303
301
|
rule.cursorVersion,
|
|
304
|
-
rule.verifiedCursorVersion ?? '',
|
|
305
302
|
rule.cursorCommit,
|
|
306
303
|
rule.supportStatus,
|
|
307
|
-
rule.takeoverPlanId,
|
|
308
304
|
String(rule.revision ?? 1),
|
|
309
305
|
].join(':');
|
|
310
306
|
}
|
|
@@ -318,6 +314,27 @@ function safeEqualHex(left: string, right: string) {
|
|
|
318
314
|
return timingSafeEqual(leftBuffer, rightBuffer);
|
|
319
315
|
}
|
|
320
316
|
|
|
317
|
+
function cursorVersionFamily(version: string) {
|
|
318
|
+
const match = version.match(/^(\d+\.\d+)(?:\.|$)/);
|
|
319
|
+
return match?.[1];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function compatEntryMatches(
|
|
323
|
+
candidate: CompatibilityManifestEntry,
|
|
324
|
+
cursor: CursorInfo,
|
|
325
|
+
environment: CliEnvironment,
|
|
326
|
+
) {
|
|
327
|
+
if (candidate.platform !== environment.platform || candidate.arch !== environment.arch) {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const versionMatches =
|
|
331
|
+
candidate.cursorVersion === cursor.version ||
|
|
332
|
+
candidate.cursorVersion === cursorVersionFamily(cursor.version);
|
|
333
|
+
const commitMatches =
|
|
334
|
+
candidate.cursorCommit === '*' || candidate.cursorCommit === cursor.commit;
|
|
335
|
+
return versionMatches && commitMatches;
|
|
336
|
+
}
|
|
337
|
+
|
|
321
338
|
export function buildCompatManifestSignature(
|
|
322
339
|
version: number,
|
|
323
340
|
rules: RemoteCompatibilityManifestRule[],
|
|
@@ -356,11 +373,6 @@ export function verifyCompatManifestEnvelope(
|
|
|
356
373
|
return rules.map(({ revision, ...rule }) => rule);
|
|
357
374
|
}
|
|
358
375
|
|
|
359
|
-
function officialCursorMajorVersion(cursorVersion: string) {
|
|
360
|
-
const match = cursorVersion.match(/^(\d+\.\d+)(?:\.|$)/);
|
|
361
|
-
return match?.[1] ?? cursorVersion;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
376
|
export function compatManifestUrlFromApiBaseUrl(apiBaseUrl: string) {
|
|
365
377
|
return `${apiBaseUrl.replace(/\/+$/, '')}/api/client/compatibility/manifest`;
|
|
366
378
|
}
|
|
@@ -407,12 +419,7 @@ export function resolveCompatEntry(
|
|
|
407
419
|
) {
|
|
408
420
|
const entries = options.entries ?? DEFAULT_COMPAT_ENTRIES;
|
|
409
421
|
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),
|
|
422
|
+
(candidate) => compatEntryMatches(candidate, cursor, environment),
|
|
416
423
|
);
|
|
417
424
|
|
|
418
425
|
if (!entry) {
|
package/src/cursor.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { execFile } from 'node:child_process';
|
|
1
|
+
import { execFile, execFileSync } from 'node:child_process';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { promisify } from 'node:util';
|
|
4
4
|
import { chmod, mkdir, readFile, rm, stat } from 'node:fs/promises';
|
|
5
|
-
import { basename, join, win32 } from 'node:path';
|
|
5
|
+
import { basename, dirname, join, win32 } from 'node:path';
|
|
6
6
|
import { homedir } from 'node:os';
|
|
7
7
|
|
|
8
8
|
export const DEFAULT_MACOS_CURSOR_APP_PATH = '/Applications/Cursor.app';
|
|
9
9
|
const execFileAsync = promisify(execFile);
|
|
10
|
+
type ExecFileForCursor = (
|
|
11
|
+
command: string,
|
|
12
|
+
args: string[],
|
|
13
|
+
) => Promise<{ stdout: string }>;
|
|
14
|
+
type ExecFileSyncForCursor = (command: string, args: string[]) => string | Buffer;
|
|
10
15
|
|
|
11
16
|
export type CursorInfo = {
|
|
12
17
|
appPath: string;
|
|
@@ -20,6 +25,8 @@ export type FindCursorOptions = {
|
|
|
20
25
|
platform?: NodeJS.Platform;
|
|
21
26
|
env?: NodeJS.ProcessEnv;
|
|
22
27
|
appImageExtract?: (appImagePath: string, outputRoot: string) => Promise<string>;
|
|
28
|
+
execFile?: ExecFileForCursor;
|
|
29
|
+
execFileSync?: ExecFileSyncForCursor;
|
|
23
30
|
};
|
|
24
31
|
|
|
25
32
|
type CursorProductJson = {
|
|
@@ -29,7 +36,17 @@ type CursorProductJson = {
|
|
|
29
36
|
cursorCommit?: unknown;
|
|
30
37
|
};
|
|
31
38
|
|
|
32
|
-
|
|
39
|
+
function inferLinuxCursorRoot(launcher: string) {
|
|
40
|
+
const binDir = dirname(launcher);
|
|
41
|
+
if (basename(binDir) === 'bin') {
|
|
42
|
+
return dirname(binDir);
|
|
43
|
+
}
|
|
44
|
+
throw new Error(`Cursor app auto-detection could not infer app root from ${launcher}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function defaultCursorAppPath(
|
|
48
|
+
options: Pick<FindCursorOptions, 'platform' | 'env' | 'execFileSync'> = {},
|
|
49
|
+
) {
|
|
33
50
|
const platform = options.platform ?? process.platform;
|
|
34
51
|
if (platform === 'darwin') {
|
|
35
52
|
return DEFAULT_MACOS_CURSOR_APP_PATH;
|
|
@@ -41,15 +58,39 @@ export function defaultCursorAppPath(options: Pick<FindCursorOptions, 'platform'
|
|
|
41
58
|
}
|
|
42
59
|
return win32.join(localAppData, 'Programs', 'Cursor');
|
|
43
60
|
}
|
|
61
|
+
if (platform === 'linux') {
|
|
62
|
+
const run = options.execFileSync ?? execFileSync;
|
|
63
|
+
const which = String(run('which', ['cursor'])).trim();
|
|
64
|
+
if (!which) {
|
|
65
|
+
throw new Error('Cursor app auto-detection could not find cursor on PATH');
|
|
66
|
+
}
|
|
67
|
+
const launcher = String(run('readlink', ['-f', which])).trim() || which;
|
|
68
|
+
return inferLinuxCursorRoot(launcher);
|
|
69
|
+
}
|
|
44
70
|
throw new Error(`Cursor app auto-detection is not supported on ${platform}`);
|
|
45
71
|
}
|
|
46
72
|
|
|
73
|
+
async function defaultLinuxCursorAppPath(options: Pick<FindCursorOptions, 'execFile'> = {}) {
|
|
74
|
+
const run = options.execFile ?? execFileAsync;
|
|
75
|
+
const which = (await run('which', ['cursor'])).stdout.trim();
|
|
76
|
+
if (!which) {
|
|
77
|
+
throw new Error('Cursor app auto-detection could not find cursor on PATH');
|
|
78
|
+
}
|
|
79
|
+
const launcher = (await run('readlink', ['-f', which])).stdout.trim() || which;
|
|
80
|
+
return inferLinuxCursorRoot(launcher);
|
|
81
|
+
}
|
|
82
|
+
|
|
47
83
|
function readString(value: unknown) {
|
|
48
84
|
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
49
85
|
}
|
|
50
86
|
|
|
51
87
|
export async function findCursor(options: FindCursorOptions = {}): Promise<CursorInfo> {
|
|
52
|
-
const
|
|
88
|
+
const platform = options.platform ?? process.platform;
|
|
89
|
+
const rawAppPath =
|
|
90
|
+
options.appPath ??
|
|
91
|
+
(platform === 'linux'
|
|
92
|
+
? await defaultLinuxCursorAppPath(options)
|
|
93
|
+
: defaultCursorAppPath(options));
|
|
53
94
|
const appPath = await resolveCursorAppPath(rawAppPath, options);
|
|
54
95
|
const productJsonPath = await resolveProductJsonPath(appPath, options);
|
|
55
96
|
const product = JSON.parse(await readFile(productJsonPath, 'utf8')) as CursorProductJson;
|
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.10',
|
|
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.10';
|
|
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.10';
|
|
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 };
|