@cursorpool-dev/cli 0.5.6 → 0.5.8
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 +116 -46
- package/node_modules/@cursor-pool/extension/package.json +3 -3
- package/node_modules/@cursor-pool/extension/src/api.ts +17 -2
- package/node_modules/@cursor-pool/extension/src/panel.ts +26 -3
- package/node_modules/@cursor-pool/extension/test/panel.test.ts +34 -1
- package/node_modules/@cursor-pool/patcher/package.json +2 -2
- package/node_modules/@cursor-pool/patcher/src/marker.ts +5 -1
- package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +58 -7
- package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +20 -0
- package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +193 -2
- package/node_modules/@cursor-pool/service/package.json +2 -2
- package/node_modules/@cursor-pool/service/src/platformSession.ts +30 -7
- package/node_modules/@cursor-pool/service/src/server.ts +1 -0
- package/node_modules/@cursor-pool/service/test/platformSession.test.ts +5 -4
- package/node_modules/@cursor-pool/service/test/server.test.ts +130 -0
- package/node_modules/@cursor-pool/shared/package.json +1 -1
- package/node_modules/@cursor-pool/shared/src/manifest.ts +35 -0
- package/node_modules/@cursor-pool/shared/test/manifest.test.ts +43 -9
- package/node_modules/@cursor-pool/takeover-plans/package.json +12 -0
- package/node_modules/@cursor-pool/takeover-plans/src/index.ts +22 -0
- package/node_modules/@cursor-pool/takeover-plans/src/plans.ts +37 -0
- package/node_modules/@cursor-pool/takeover-plans/src/types.ts +9 -0
- package/node_modules/@cursor-pool/takeover-plans/test/registry.test.ts +23 -0
- package/node_modules/@esbuild/linux-x64/README.md +3 -0
- package/node_modules/@esbuild/linux-x64/bin/esbuild +0 -0
- package/node_modules/@esbuild/linux-x64/package.json +20 -0
- package/node_modules/esbuild/LICENSE.md +21 -0
- package/node_modules/esbuild/README.md +3 -0
- package/node_modules/esbuild/bin/esbuild +223 -0
- package/node_modules/esbuild/install.js +300 -0
- package/node_modules/esbuild/lib/main.d.ts +716 -0
- package/node_modules/esbuild/lib/main.js +2532 -0
- package/node_modules/esbuild/package.json +74 -0
- package/node_modules/tsx/LICENSE +21 -0
- package/node_modules/tsx/README.md +32 -0
- package/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
- package/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
- package/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
- package/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
- package/node_modules/tsx/dist/cjs/index.cjs +1 -0
- package/node_modules/tsx/dist/cjs/index.mjs +1 -0
- package/node_modules/tsx/dist/cli.cjs +54 -0
- package/node_modules/tsx/dist/cli.mjs +55 -0
- package/node_modules/tsx/dist/client-D3mGB526.cjs +1 -0
- package/node_modules/tsx/dist/client-D_mPDF5S.mjs +1 -0
- package/node_modules/tsx/dist/esm/api/index.cjs +1 -0
- package/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
- package/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
- package/node_modules/tsx/dist/esm/api/index.mjs +1 -0
- package/node_modules/tsx/dist/esm/index.cjs +1 -0
- package/node_modules/tsx/dist/esm/index.mjs +1 -0
- package/node_modules/tsx/dist/get-pipe-path-D4YM6rQt.cjs +1 -0
- package/node_modules/tsx/dist/get-pipe-path-_tAJyU_v.mjs +1 -0
- package/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
- package/node_modules/tsx/dist/index-D9F1FXzN.cjs +14 -0
- package/node_modules/tsx/dist/index-XurvG3JN.mjs +14 -0
- package/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
- package/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
- package/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
- package/node_modules/tsx/dist/loader.cjs +1 -0
- package/node_modules/tsx/dist/loader.mjs +1 -0
- package/node_modules/tsx/dist/node-features-B9BBLzwu.mjs +1 -0
- package/node_modules/tsx/dist/node-features-CQLdkVE6.cjs +1 -0
- package/node_modules/tsx/dist/package-CGdS2_oX.cjs +1 -0
- package/node_modules/tsx/dist/package-DyJMwVU5.mjs +1 -0
- package/node_modules/tsx/dist/patch-repl.cjs +1 -0
- package/node_modules/tsx/dist/patch-repl.mjs +1 -0
- package/node_modules/tsx/dist/preflight.cjs +1 -0
- package/node_modules/tsx/dist/preflight.mjs +1 -0
- package/node_modules/tsx/dist/register-BOkp8V6j.cjs +10 -0
- package/node_modules/tsx/dist/register-BnTWPeIB.mjs +10 -0
- package/node_modules/tsx/dist/register-CHVGxKtC.cjs +2 -0
- package/node_modules/tsx/dist/register-D_B8UL5H.mjs +2 -0
- package/node_modules/tsx/dist/repl.cjs +3 -0
- package/node_modules/tsx/dist/repl.mjs +3 -0
- package/node_modules/tsx/dist/require-CjvaJWEr.cjs +1 -0
- package/node_modules/tsx/dist/require-DzmC1hVr.mjs +1 -0
- package/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
- package/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
- package/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
- package/node_modules/tsx/dist/temporary-directory-BDDVQOvU.mjs +1 -0
- package/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
- package/node_modules/tsx/package.json +67 -0
- package/package.json +11 -6
- package/src/autostart.ts +5 -1
- package/src/compat.ts +193 -47
- package/src/cursor.ts +59 -3
- package/src/extensionBundle.ts +1 -1
- package/src/extensionLink.ts +28 -7
- package/src/install.ts +176 -24
- package/src/installRecord.ts +2 -0
- package/src/patchSet.ts +12 -6
- package/src/platform.ts +3 -3
- package/src/repair.ts +10 -1
- package/src/restore.ts +12 -4
- package/src/serviceProcess.ts +2 -1
- package/src/status.ts +6 -0
- package/src/trial.ts +1 -0
- package/test/autostart.test.ts +23 -2
- package/test/compat.test.ts +238 -3
- package/test/cursor-pool-bin.test.ts +1 -0
- package/test/cursor.test.ts +60 -1
- package/test/e2e-install.test.ts +53 -0
- package/test/extensionLink.test.ts +48 -2
- package/test/install.test.ts +191 -6
- package/test/repair.test.ts +1 -0
- package/test/serviceProcess.test.ts +10 -1
- package/test/status.test.ts +1 -0
package/src/compat.ts
CHANGED
|
@@ -5,72 +5,171 @@ import type {
|
|
|
5
5
|
CompatibilityManifestEntry,
|
|
6
6
|
CompatibilityManifestEnvelope,
|
|
7
7
|
} from '@cursor-pool/shared/manifest';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
10
|
+
CURSOR_WORKBENCH_RELATIVE_PATH,
|
|
11
|
+
} from '@cursor-pool/patcher';
|
|
9
12
|
import type { CliEnvironment } from './environment';
|
|
10
13
|
import type { CursorInfo } from './cursor';
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
function macPatchTargets(agentSha256: string, workbenchSha256: string) {
|
|
16
|
+
return [
|
|
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 {
|
|
14
48
|
platform: 'darwin',
|
|
15
|
-
arch:
|
|
16
|
-
|
|
17
|
-
|
|
49
|
+
arch: input.arch,
|
|
50
|
+
officialSourceUrl: 'https://cursor.com/download',
|
|
51
|
+
officialDownloadUrl: `https://api2.cursor.sh/updates/download/golden/darwin-${input.arch}/cursor/${input.officialMajorVersion}`,
|
|
52
|
+
officialDownloadPlatform: `darwin-${input.arch}`,
|
|
53
|
+
verifiedCursorVersion: input.verifiedCursorVersion,
|
|
54
|
+
cursorVersion: input.officialMajorVersion,
|
|
55
|
+
cursorCommit: input.cursorCommit,
|
|
18
56
|
supportStatus: 'supported',
|
|
57
|
+
adapterVersion: input.adapterVersion,
|
|
58
|
+
takeoverPlanId: input.takeoverPlanId,
|
|
59
|
+
structureFamily: input.structureFamily,
|
|
60
|
+
patchTargets: macPatchTargets(input.agentSha256, input.workbenchSha256),
|
|
19
61
|
targetRelativePath: CURSOR_AGENT_EXEC_RELATIVE_PATH,
|
|
20
|
-
expectedSha256:
|
|
21
|
-
structureSignature:
|
|
62
|
+
expectedSha256: input.agentSha256,
|
|
63
|
+
structureSignature: input.structureFamily,
|
|
22
64
|
patchStrategy: 'cursor-agent-exec-snippet',
|
|
23
65
|
verifyMarker: 'cursor-pool',
|
|
24
66
|
restoreStrategy: 'external-backup',
|
|
25
|
-
minCliVersion: '0.5.
|
|
26
|
-
minExtensionVersion: '0.5.
|
|
27
|
-
minServiceVersion: '0.5.
|
|
67
|
+
minCliVersion: '0.5.8',
|
|
68
|
+
minExtensionVersion: '0.5.8',
|
|
69
|
+
minServiceVersion: '0.5.8',
|
|
28
70
|
requiresWritableAppBundle: true,
|
|
29
71
|
requiresAdHocResign: true,
|
|
30
|
-
userMessage:
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
72
|
+
userMessage: input.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({
|
|
34
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({
|
|
104
|
+
arch: 'arm64',
|
|
105
|
+
officialMajorVersion: '3.5',
|
|
106
|
+
verifiedCursorVersion: '3.5.38',
|
|
35
107
|
cursorVersion: '3.5.38',
|
|
36
108
|
cursorCommit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
109
|
+
adapterVersion: '0.5.8',
|
|
110
|
+
structureFamily: 'mac-agent-F-workbench-p-L0',
|
|
111
|
+
takeoverPlanId: 'cursor-3.5-mac-agent-f-workbench-p-l0',
|
|
112
|
+
agentSha256: 'cb18f0237278884a39e2ce2b8664255e12689ad0803c20096c38e86c36acc51f',
|
|
113
|
+
workbenchSha256: '19762fb81b7d5f1a42ffa8c0c487648432874d0892cfcdb32824b107f6dcf99d',
|
|
114
|
+
userMessage: 'Cursor 3.5.38 macOS arm64 is supported by the v0.5 adapter.',
|
|
115
|
+
}),
|
|
116
|
+
macCompatEntry({
|
|
117
|
+
arch: 'x64',
|
|
118
|
+
officialMajorVersion: '3.5',
|
|
119
|
+
verifiedCursorVersion: '3.5.38',
|
|
120
|
+
cursorVersion: '3.5.38',
|
|
121
|
+
cursorCommit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
122
|
+
adapterVersion: '0.5.8',
|
|
123
|
+
structureFamily: 'mac-agent-F-workbench-p-L0',
|
|
124
|
+
takeoverPlanId: 'cursor-3.5-mac-agent-f-workbench-p-l0',
|
|
125
|
+
agentSha256: 'cb18f0237278884a39e2ce2b8664255e12689ad0803c20096c38e86c36acc51f',
|
|
126
|
+
workbenchSha256: '19762fb81b7d5f1a42ffa8c0c487648432874d0892cfcdb32824b107f6dcf99d',
|
|
127
|
+
userMessage: 'Cursor 3.5.38 macOS x64 is supported by the v0.5 adapter.',
|
|
128
|
+
}),
|
|
129
|
+
macCompatEntry({
|
|
53
130
|
arch: 'arm64',
|
|
131
|
+
officialMajorVersion: '3.6',
|
|
132
|
+
verifiedCursorVersion: '3.6.21',
|
|
54
133
|
cursorVersion: '3.6.21',
|
|
55
134
|
cursorCommit: 'e7a7e93f4d75f8272503ecf33cedbaae10114a10',
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
135
|
+
adapterVersion: '0.5.8',
|
|
136
|
+
structureFamily: 'mac-agent-c-workbench-h-uv',
|
|
137
|
+
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
138
|
+
agentSha256: '222512631b78fddcdca3fa76c0dd458a7a86751dde19c998ceb31b3fe1905ebf',
|
|
139
|
+
workbenchSha256: '97562e30eebf41b9e162eb100966a2caf09c1c2fcf55bc87d5a84f9de67511f5',
|
|
140
|
+
userMessage: 'Cursor 3.6.21 macOS arm64 is supported by the v0.5 adapter.',
|
|
141
|
+
}),
|
|
142
|
+
macCompatEntry({
|
|
143
|
+
arch: 'arm64',
|
|
144
|
+
officialMajorVersion: '3.6',
|
|
145
|
+
verifiedCursorVersion: '3.6.31',
|
|
146
|
+
cursorVersion: '3.6.31',
|
|
147
|
+
cursorCommit: '81fcf2931d7687b4ff3f3017858d0c6dee7e2a60',
|
|
148
|
+
adapterVersion: '0.5.8',
|
|
149
|
+
structureFamily: 'mac-agent-c-workbench-h-uv',
|
|
150
|
+
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
151
|
+
agentSha256: '05bfa29eacb8271c378765ead4bf881f806b97549dd13367183aa7a9331c1131',
|
|
152
|
+
workbenchSha256: '97562e30eebf41b9e162eb100966a2caf09c1c2fcf55bc87d5a84f9de67511f5',
|
|
153
|
+
userMessage: 'Cursor 3.6.31 macOS arm64 is supported by the v0.5 adapter.',
|
|
154
|
+
}),
|
|
155
|
+
macCompatEntry({
|
|
156
|
+
arch: 'arm64',
|
|
157
|
+
officialMajorVersion: '3.7',
|
|
158
|
+
verifiedCursorVersion: '3.7.12',
|
|
159
|
+
cursorVersion: '3.7.12',
|
|
160
|
+
cursorCommit: 'b887a26c4f70bd8136bfffeda812b24194ec9ce0',
|
|
161
|
+
adapterVersion: '0.6.0',
|
|
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
|
+
}),
|
|
70
168
|
];
|
|
71
169
|
|
|
72
170
|
export type ResolveCompatOptions = {
|
|
73
171
|
entries?: CompatibilityManifestEntry[];
|
|
172
|
+
adapterVersion?: string;
|
|
74
173
|
};
|
|
75
174
|
|
|
76
175
|
export type CompatManifestFetchResponse = {
|
|
@@ -121,6 +220,34 @@ function asBoolean(value: unknown, field: string) {
|
|
|
121
220
|
return value;
|
|
122
221
|
}
|
|
123
222
|
|
|
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
|
+
|
|
124
251
|
function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
125
252
|
if (!isRecord(value)) {
|
|
126
253
|
throw new Error('compat manifest rule invalid');
|
|
@@ -136,12 +263,23 @@ function normalizeRule(value: unknown): RemoteCompatibilityManifestRule {
|
|
|
136
263
|
) {
|
|
137
264
|
throw new Error('compat manifest revision invalid');
|
|
138
265
|
}
|
|
266
|
+
const adapterVersion = asOptionalString(value.adapterVersion, 'adapterVersion');
|
|
267
|
+
const structureFamily = asOptionalString(value.structureFamily, 'structureFamily');
|
|
268
|
+
const patchTargets = normalizePatchTargets(value.patchTargets);
|
|
139
269
|
return {
|
|
140
270
|
platform: asString(value.platform, 'platform'),
|
|
141
271
|
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') }),
|
|
142
276
|
cursorVersion: asString(value.cursorVersion, 'cursorVersion'),
|
|
143
277
|
cursorCommit: asString(value.cursorCommit, 'cursorCommit'),
|
|
144
278
|
supportStatus,
|
|
279
|
+
...(adapterVersion === undefined ? {} : { adapterVersion }),
|
|
280
|
+
takeoverPlanId: asString(value.takeoverPlanId, 'takeoverPlanId'),
|
|
281
|
+
...(structureFamily === undefined ? {} : { structureFamily }),
|
|
282
|
+
...(patchTargets === undefined ? {} : { patchTargets }),
|
|
145
283
|
targetRelativePath: asString(value.targetRelativePath, 'targetRelativePath'),
|
|
146
284
|
expectedSha256: asString(value.expectedSha256, 'expectedSha256'),
|
|
147
285
|
structureSignature: asString(value.structureSignature, 'structureSignature'),
|
|
@@ -163,8 +301,10 @@ function canonicalRuleSegment(rule: RemoteCompatibilityManifestRule) {
|
|
|
163
301
|
rule.platform,
|
|
164
302
|
rule.arch,
|
|
165
303
|
rule.cursorVersion,
|
|
304
|
+
rule.verifiedCursorVersion ?? '',
|
|
166
305
|
rule.cursorCommit,
|
|
167
306
|
rule.supportStatus,
|
|
307
|
+
rule.takeoverPlanId,
|
|
168
308
|
String(rule.revision ?? 1),
|
|
169
309
|
].join(':');
|
|
170
310
|
}
|
|
@@ -216,6 +356,11 @@ export function verifyCompatManifestEnvelope(
|
|
|
216
356
|
return rules.map(({ revision, ...rule }) => rule);
|
|
217
357
|
}
|
|
218
358
|
|
|
359
|
+
function officialCursorMajorVersion(cursorVersion: string) {
|
|
360
|
+
const match = cursorVersion.match(/^(\d+\.\d+)(?:\.|$)/);
|
|
361
|
+
return match?.[1] ?? cursorVersion;
|
|
362
|
+
}
|
|
363
|
+
|
|
219
364
|
export function compatManifestUrlFromApiBaseUrl(apiBaseUrl: string) {
|
|
220
365
|
return `${apiBaseUrl.replace(/\/+$/, '')}/api/client/compatibility/manifest`;
|
|
221
366
|
}
|
|
@@ -265,8 +410,9 @@ export function resolveCompatEntry(
|
|
|
265
410
|
(candidate) =>
|
|
266
411
|
candidate.platform === environment.platform &&
|
|
267
412
|
candidate.arch === environment.arch &&
|
|
268
|
-
candidate.cursorVersion === cursor.version &&
|
|
269
|
-
candidate.cursorCommit === cursor.commit
|
|
413
|
+
candidate.cursorVersion === officialCursorMajorVersion(cursor.version) &&
|
|
414
|
+
candidate.cursorCommit === cursor.commit &&
|
|
415
|
+
(!options.adapterVersion || candidate.adapterVersion === options.adapterVersion),
|
|
270
416
|
);
|
|
271
417
|
|
|
272
418
|
if (!entry) {
|
package/src/cursor.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { createHash } from 'node:crypto';
|
|
3
|
+
import { promisify } from 'node:util';
|
|
4
|
+
import { chmod, mkdir, readFile, rm, stat } from 'node:fs/promises';
|
|
5
|
+
import { basename, join, win32 } from 'node:path';
|
|
6
|
+
import { homedir } from 'node:os';
|
|
3
7
|
|
|
4
8
|
export const DEFAULT_MACOS_CURSOR_APP_PATH = '/Applications/Cursor.app';
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
5
10
|
|
|
6
11
|
export type CursorInfo = {
|
|
7
12
|
appPath: string;
|
|
@@ -14,6 +19,7 @@ export type FindCursorOptions = {
|
|
|
14
19
|
productRelativePath?: string;
|
|
15
20
|
platform?: NodeJS.Platform;
|
|
16
21
|
env?: NodeJS.ProcessEnv;
|
|
22
|
+
appImageExtract?: (appImagePath: string, outputRoot: string) => Promise<string>;
|
|
17
23
|
};
|
|
18
24
|
|
|
19
25
|
type CursorProductJson = {
|
|
@@ -43,7 +49,8 @@ function readString(value: unknown) {
|
|
|
43
49
|
}
|
|
44
50
|
|
|
45
51
|
export async function findCursor(options: FindCursorOptions = {}): Promise<CursorInfo> {
|
|
46
|
-
const
|
|
52
|
+
const rawAppPath = options.appPath ?? defaultCursorAppPath(options);
|
|
53
|
+
const appPath = await resolveCursorAppPath(rawAppPath, options);
|
|
47
54
|
const productJsonPath = await resolveProductJsonPath(appPath, options);
|
|
48
55
|
const product = JSON.parse(await readFile(productJsonPath, 'utf8')) as CursorProductJson;
|
|
49
56
|
const version = readString(product.version);
|
|
@@ -66,6 +73,55 @@ export async function findCursor(options: FindCursorOptions = {}): Promise<Curso
|
|
|
66
73
|
};
|
|
67
74
|
}
|
|
68
75
|
|
|
76
|
+
async function pathIsFile(path: string) {
|
|
77
|
+
try {
|
|
78
|
+
return (await stat(path)).isFile();
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function linuxAppImageExtractRoot(appImagePath: string) {
|
|
85
|
+
const hash = createHash('sha256').update(appImagePath).digest('hex').slice(0, 16);
|
|
86
|
+
const name = basename(appImagePath).replace(/\.AppImage$/i, '').replace(/[^A-Za-z0-9._-]/g, '-');
|
|
87
|
+
return join(homedir(), '.cursor-pool/appimages', `${name}-${hash}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function defaultExtractLinuxAppImage(appImagePath: string, outputRoot: string) {
|
|
91
|
+
await rm(outputRoot, { recursive: true, force: true });
|
|
92
|
+
await mkdir(outputRoot, { recursive: true });
|
|
93
|
+
await chmod(appImagePath, 0o755).catch(() => undefined);
|
|
94
|
+
await execFileAsync(appImagePath, ['--appimage-extract'], {
|
|
95
|
+
cwd: outputRoot,
|
|
96
|
+
maxBuffer: 1024 * 1024 * 20,
|
|
97
|
+
});
|
|
98
|
+
return join(outputRoot, 'squashfs-root');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function resolveCursorAppPath(appPath: string, options: FindCursorOptions) {
|
|
102
|
+
if (
|
|
103
|
+
(options.platform ?? process.platform) !== 'linux' ||
|
|
104
|
+
!/\.AppImage$/i.test(appPath) ||
|
|
105
|
+
!(await pathIsFile(appPath))
|
|
106
|
+
) {
|
|
107
|
+
return appPath;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const outputRoot = linuxAppImageExtractRoot(appPath);
|
|
111
|
+
const extractedPath = join(outputRoot, 'squashfs-root');
|
|
112
|
+
try {
|
|
113
|
+
await readFile(join(extractedPath, 'usr/share/cursor/resources/app/product.json'), 'utf8');
|
|
114
|
+
return extractedPath;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const extract = options.appImageExtract ?? defaultExtractLinuxAppImage;
|
|
122
|
+
return extract(appPath, outputRoot);
|
|
123
|
+
}
|
|
124
|
+
|
|
69
125
|
async function resolveProductJsonPath(appPath: string, options: FindCursorOptions) {
|
|
70
126
|
if (options.productRelativePath) {
|
|
71
127
|
return join(appPath, options.productRelativePath);
|
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.8',
|
|
59
59
|
displayName: 'Cursor Pool 平台模式',
|
|
60
60
|
publisher: 'cursor-pool',
|
|
61
61
|
type: sourceManifest.type,
|
package/src/extensionLink.ts
CHANGED
|
@@ -4,7 +4,8 @@ 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.
|
|
7
|
+
export const LINKED_EXTENSION_DIRNAME = 'cursor-pool.extension-0.5.8';
|
|
8
|
+
const LINKED_EXTENSION_DIRNAME_PREFIX = 'cursor-pool.extension-';
|
|
8
9
|
const RUNTIME_EXTENSION_ID = 'cursor-pool.cursorpool';
|
|
9
10
|
const STALE_EXTENSION_IDS = new Set([
|
|
10
11
|
RUNTIME_EXTENSION_ID,
|
|
@@ -48,10 +49,17 @@ async function readRuntimeManifest(linkedPath: string) {
|
|
|
48
49
|
};
|
|
49
50
|
const publisher = typeof manifest.publisher === 'string' ? manifest.publisher : 'cursor-pool';
|
|
50
51
|
const name = typeof manifest.name === 'string' ? manifest.name : 'cursorpool';
|
|
51
|
-
const version = typeof manifest.version === 'string' ? manifest.version : '0.5.
|
|
52
|
+
const version = typeof manifest.version === 'string' ? manifest.version : '0.5.8';
|
|
52
53
|
return { id: `${publisher}.${name}`, version };
|
|
53
54
|
}
|
|
54
55
|
|
|
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
|
+
|
|
55
63
|
export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string, linkedPath: string) {
|
|
56
64
|
const indexPath = join(resolveExtensionInstallPath(cursorExtensionsDir), 'extensions.json');
|
|
57
65
|
if (!(await exists(indexPath))) {
|
|
@@ -63,11 +71,13 @@ export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string,
|
|
|
63
71
|
relativeLocation?: string;
|
|
64
72
|
}>;
|
|
65
73
|
const manifest = await readRuntimeManifest(linkedPath);
|
|
74
|
+
const relativeLocation = basename(linkedPath);
|
|
66
75
|
const nextEntries = entries.filter((entry) => {
|
|
67
76
|
const id = entry.identifier?.id;
|
|
77
|
+
const relativeLocation = entry.relativeLocation ?? '';
|
|
68
78
|
return (
|
|
69
79
|
!STALE_EXTENSION_IDS.has(id ?? '') &&
|
|
70
|
-
|
|
80
|
+
!relativeLocation.startsWith(LINKED_EXTENSION_DIRNAME_PREFIX) &&
|
|
71
81
|
entry.relativeLocation !== 'keg1255.cursorpool-1.0.52'
|
|
72
82
|
);
|
|
73
83
|
});
|
|
@@ -79,7 +89,7 @@ export async function refreshCursorExtensionsIndex(cursorExtensionsDir: string,
|
|
|
79
89
|
path: linkedPath,
|
|
80
90
|
scheme: 'file',
|
|
81
91
|
},
|
|
82
|
-
relativeLocation
|
|
92
|
+
relativeLocation,
|
|
83
93
|
version: manifest.version,
|
|
84
94
|
});
|
|
85
95
|
await writeFile(indexPath, `${JSON.stringify(nextEntries, null, 2)}\n`, 'utf8');
|
|
@@ -92,9 +102,9 @@ function assertSafeLinkedExtensionPath(linkedPath: string) {
|
|
|
92
102
|
(segment) => segment === 'extensions' || segment === 'Extensions',
|
|
93
103
|
);
|
|
94
104
|
|
|
95
|
-
if (basename(resolvedLinkedPath)
|
|
105
|
+
if (!basename(resolvedLinkedPath).startsWith(LINKED_EXTENSION_DIRNAME_PREFIX) || !hasExtensionsParent) {
|
|
96
106
|
throw new Error(
|
|
97
|
-
`Unsafe linked extension path for recursive removal: ${linkedPath}. Expected an extensions/${
|
|
107
|
+
`Unsafe linked extension path for recursive removal: ${linkedPath}. Expected an extensions/${LINKED_EXTENSION_DIRNAME_PREFIX}<version> bundle path.`,
|
|
98
108
|
);
|
|
99
109
|
}
|
|
100
110
|
}
|
|
@@ -103,6 +113,14 @@ export function linkedExtensionPathForDir(cursorExtensionsDir: string) {
|
|
|
103
113
|
return join(resolveExtensionInstallPath(cursorExtensionsDir), LINKED_EXTENSION_DIRNAME);
|
|
104
114
|
}
|
|
105
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
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
106
124
|
export async function getLinkedExtensionState(linkedPath: string | undefined): Promise<LinkedExtensionState> {
|
|
107
125
|
if (!linkedPath) {
|
|
108
126
|
return 'missing';
|
|
@@ -119,7 +137,10 @@ export async function linkExtensionBundle({
|
|
|
119
137
|
cursorExtensionsDir,
|
|
120
138
|
}: LinkExtensionBundleOptions): Promise<LinkExtensionBundleResult> {
|
|
121
139
|
const resolvedSourceBundlePath = resolveExtensionInstallPath(sourceBundlePath);
|
|
122
|
-
const linkedPath =
|
|
140
|
+
const linkedPath =
|
|
141
|
+
(await getLinkedExtensionState(resolvedSourceBundlePath)) === 'missing'
|
|
142
|
+
? linkedExtensionPathForDir(cursorExtensionsDir)
|
|
143
|
+
: await linkedExtensionPathForSource(cursorExtensionsDir, resolvedSourceBundlePath);
|
|
123
144
|
|
|
124
145
|
if ((await getLinkedExtensionState(resolvedSourceBundlePath)) === 'missing') {
|
|
125
146
|
return { state: 'missing', linkedPath };
|