@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/test/install.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
-
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { mkdir, mkdtemp, readFile, rm, stat, writeFile } from 'node:fs/promises';
|
|
4
4
|
import { tmpdir } from 'node:os';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
6
|
import test from 'node:test';
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
CURSOR_POOL_AGENT_EXEC_PROVIDER_REGISTER_ANCHOR,
|
|
9
9
|
CURSOR_POOL_PATCH_MARKER,
|
|
10
10
|
} from '../../patcher/src/marker';
|
|
11
|
-
import { writeRuntimeInfo } from '../../service/src/runtime';
|
|
11
|
+
import { readRuntimeInfo, writeRuntimeInfo } from '../../service/src/runtime';
|
|
12
12
|
import type { CompatibilityManifestEntry } from '../../shared/src/manifest';
|
|
13
13
|
import { buildCompatManifestSignature } from '../src/compat';
|
|
14
14
|
import { getExtensionState } from '../src/extensionBundle';
|
|
@@ -69,15 +69,36 @@ async function createFixtureApp() {
|
|
|
69
69
|
);
|
|
70
70
|
await writeFile(targetPath, targetContent, 'utf8');
|
|
71
71
|
await writeFile(join(appPath, alwaysLocalRelativePath), 'function alwaysLocal(){}\n', 'utf8');
|
|
72
|
-
|
|
72
|
+
const workbenchContent = workbenchFixture();
|
|
73
|
+
await writeFile(join(appPath, workbenchRelativePath), workbenchContent, 'utf8');
|
|
73
74
|
|
|
74
75
|
const expectedSha256 = createHash('sha256').update(targetContent).digest('hex');
|
|
76
|
+
const workbenchSha256 = createHash('sha256').update(workbenchContent).digest('hex');
|
|
75
77
|
const compatEntry: CompatibilityManifestEntry = {
|
|
76
78
|
platform: process.platform,
|
|
77
79
|
arch: process.arch,
|
|
78
|
-
cursorVersion: '3.5
|
|
80
|
+
cursorVersion: '3.5',
|
|
79
81
|
cursorCommit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
80
82
|
supportStatus: 'supported',
|
|
83
|
+
adapterVersion: '0.5.8',
|
|
84
|
+
takeoverPlanId: 'cursor-3.5-mac-agent-f-workbench-p-l0',
|
|
85
|
+
structureFamily: 'mac-agent-F-workbench-p-L0',
|
|
86
|
+
patchTargets: [
|
|
87
|
+
{
|
|
88
|
+
name: 'agent-exec',
|
|
89
|
+
targetRelativePath,
|
|
90
|
+
expectedSha256,
|
|
91
|
+
patchStrategy: 'cursor-agent-exec-snippet',
|
|
92
|
+
verifyMarker: 'cursor-pool',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'workbench',
|
|
96
|
+
targetRelativePath: workbenchRelativePath,
|
|
97
|
+
expectedSha256: workbenchSha256,
|
|
98
|
+
patchStrategy: 'cursor-workbench-auth-gate',
|
|
99
|
+
verifyMarker: 'cursor-pool-workbench',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
81
102
|
targetRelativePath,
|
|
82
103
|
expectedSha256,
|
|
83
104
|
structureSignature: 'fixture',
|
|
@@ -141,9 +162,10 @@ async function createLinuxFixtureApp() {
|
|
|
141
162
|
const compatEntry: CompatibilityManifestEntry = {
|
|
142
163
|
platform: 'linux',
|
|
143
164
|
arch: process.arch,
|
|
144
|
-
cursorVersion: '3.6
|
|
165
|
+
cursorVersion: '3.6',
|
|
145
166
|
cursorCommit: 'linux-commit',
|
|
146
167
|
supportStatus: 'supported',
|
|
168
|
+
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
147
169
|
targetRelativePath,
|
|
148
170
|
expectedSha256,
|
|
149
171
|
structureSignature: 'linux-fixture',
|
|
@@ -188,7 +210,7 @@ async function createRemoteOnlyFixtureApp() {
|
|
|
188
210
|
);
|
|
189
211
|
const compatEntry = {
|
|
190
212
|
...fixture.compatEntry,
|
|
191
|
-
cursorVersion: '3.7
|
|
213
|
+
cursorVersion: '3.7',
|
|
192
214
|
cursorCommit: 'remote-commit',
|
|
193
215
|
userMessage: 'remote fixture supported',
|
|
194
216
|
};
|
|
@@ -212,6 +234,7 @@ test('install reports Cursor version, simulated extension, service, patch, and h
|
|
|
212
234
|
assert.match(output, /Cursor 3\.5\.38/);
|
|
213
235
|
assert.match(output, /mode: disposable/);
|
|
214
236
|
assert.match(output, /app: .*Cursor\.app/);
|
|
237
|
+
assert.match(output, /takeover-plan: cursor-3\.5-mac-agent-f-workbench-p-l0/);
|
|
215
238
|
assert.match(output, /extension: bundled/);
|
|
216
239
|
assert.match(output, /trial: recorded/);
|
|
217
240
|
assert.match(output, /service: running/);
|
|
@@ -225,6 +248,7 @@ test('install reports Cursor version, simulated extension, service, patch, and h
|
|
|
225
248
|
|
|
226
249
|
test('install detects Linux Cursor AppImage layout under usr/share/cursor', async () => {
|
|
227
250
|
const fixture = await createLinuxFixtureApp();
|
|
251
|
+
const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
|
|
228
252
|
|
|
229
253
|
try {
|
|
230
254
|
const output = await install({
|
|
@@ -235,14 +259,20 @@ test('install detects Linux Cursor AppImage layout under usr/share/cursor', asyn
|
|
|
235
259
|
backupDir: fixture.backupDir,
|
|
236
260
|
trialRecordDir: join(fixture.tempDir, 'trials'),
|
|
237
261
|
extensionInstallPath: join(fixture.tempDir, 'extensions/cursor-pool-status'),
|
|
262
|
+
linuxLauncherFile: launcherFile,
|
|
238
263
|
compatEntries: [fixture.compatEntry],
|
|
239
264
|
stopServiceAfterInstall: true,
|
|
240
265
|
});
|
|
241
266
|
|
|
242
267
|
assert.match(output, /Cursor 3\.6\.31/);
|
|
243
268
|
assert.match(output, /patch: applied/);
|
|
269
|
+
assert.match(output, /launcher: .*cursor-pool-cursor/);
|
|
244
270
|
assert.match(output, /health: ok/);
|
|
245
271
|
assert.match(await readFile(fixture.targetPath, 'utf8'), new RegExp(CURSOR_POOL_PATCH_MARKER));
|
|
272
|
+
const launcher = await readFile(launcherFile, 'utf8');
|
|
273
|
+
assert.match(launcher, /AppRun/);
|
|
274
|
+
assert.match(launcher, /--no-sandbox/);
|
|
275
|
+
assert.equal((await stat(launcherFile)).mode & 0o111, 0o111);
|
|
246
276
|
} finally {
|
|
247
277
|
await rm(fixture.tempDir, { recursive: true, force: true });
|
|
248
278
|
}
|
|
@@ -280,6 +310,36 @@ test('install can use a signed remote compatibility manifest from api base url',
|
|
|
280
310
|
}
|
|
281
311
|
});
|
|
282
312
|
|
|
313
|
+
test('install rejects when a secondary patch target hash does not match', async () => {
|
|
314
|
+
const fixture = await createFixtureApp();
|
|
315
|
+
const compatEntry: CompatibilityManifestEntry = {
|
|
316
|
+
...fixture.compatEntry,
|
|
317
|
+
patchTargets: fixture.compatEntry.patchTargets?.map((target) =>
|
|
318
|
+
target.name === 'workbench'
|
|
319
|
+
? { ...target, expectedSha256: 'f'.repeat(64) }
|
|
320
|
+
: target,
|
|
321
|
+
),
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
await assert.rejects(
|
|
326
|
+
() =>
|
|
327
|
+
install({
|
|
328
|
+
appPath: fixture.appPath,
|
|
329
|
+
runtimeFile: fixture.runtimeFile,
|
|
330
|
+
backupDir: fixture.backupDir,
|
|
331
|
+
trialRecordDir: join(fixture.tempDir, 'trials'),
|
|
332
|
+
extensionInstallPath: join(fixture.tempDir, 'extensions/cursor-pool-status'),
|
|
333
|
+
compatEntries: [compatEntry],
|
|
334
|
+
stopServiceAfterInstall: true,
|
|
335
|
+
}),
|
|
336
|
+
/Patch target hash mismatch/,
|
|
337
|
+
);
|
|
338
|
+
} finally {
|
|
339
|
+
await rm(fixture.tempDir, { recursive: true, force: true });
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
283
343
|
test('install passes API base URL to detached service startup', async () => {
|
|
284
344
|
const fixture = await createFixtureApp();
|
|
285
345
|
const serviceCalls: Record<string, unknown>[] = [];
|
|
@@ -350,6 +410,124 @@ test('install persists API base URL and installs user autostart for real client
|
|
|
350
410
|
}
|
|
351
411
|
});
|
|
352
412
|
|
|
413
|
+
test('Linux real install falls back to user systemd when detached service startup is unhealthy', async () => {
|
|
414
|
+
const fixture = await createLinuxFixtureApp();
|
|
415
|
+
const configFile = join(fixture.tempDir, 'client-config.json');
|
|
416
|
+
const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
|
|
417
|
+
const installRecordFile = join(fixture.tempDir, 'install.json');
|
|
418
|
+
const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
|
|
419
|
+
const calls: string[] = [];
|
|
420
|
+
|
|
421
|
+
try {
|
|
422
|
+
const output = await install({
|
|
423
|
+
realAppPath: fixture.appPath,
|
|
424
|
+
yes: true,
|
|
425
|
+
platform: 'linux',
|
|
426
|
+
arch: process.arch,
|
|
427
|
+
runtimeFile: fixture.runtimeFile,
|
|
428
|
+
backupDir: fixture.backupDir,
|
|
429
|
+
installRecordFile,
|
|
430
|
+
cursorExtensionsDir,
|
|
431
|
+
clientConfigFile: configFile,
|
|
432
|
+
linuxLauncherFile: launcherFile,
|
|
433
|
+
compatEntries: [fixture.compatEntry],
|
|
434
|
+
startDetachedService: async () => {
|
|
435
|
+
calls.push('detached');
|
|
436
|
+
throw new Error('Detached service failed to become healthy');
|
|
437
|
+
},
|
|
438
|
+
installUserAutostart: async (options) => {
|
|
439
|
+
calls.push('autostart');
|
|
440
|
+
await writeRuntimeInfo(
|
|
441
|
+
{ host: '127.0.0.1', port: 56393, runtimeId: 'systemd-runtime' },
|
|
442
|
+
{ runtimeFile: options.runtimeFile },
|
|
443
|
+
);
|
|
444
|
+
return { state: 'installed' as const };
|
|
445
|
+
},
|
|
446
|
+
fetchHealth: async (url) => {
|
|
447
|
+
calls.push(`health:${url}`);
|
|
448
|
+
return { ok: true, healthy: true };
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
assert.deepEqual(calls, [
|
|
453
|
+
'detached',
|
|
454
|
+
'autostart',
|
|
455
|
+
'health:http://127.0.0.1:56393/health',
|
|
456
|
+
'health:http://127.0.0.1:56393/health',
|
|
457
|
+
]);
|
|
458
|
+
assert.match(output, /mode: real/);
|
|
459
|
+
assert.match(output, /service: running 127\.0\.0\.1:56393/);
|
|
460
|
+
assert.match(output, /autostart: installed/);
|
|
461
|
+
assert.match(output, /health: ok/);
|
|
462
|
+
assert.deepEqual(await readRuntimeInfo({ runtimeFile: fixture.runtimeFile }), {
|
|
463
|
+
host: '127.0.0.1',
|
|
464
|
+
port: 56393,
|
|
465
|
+
runtimeId: 'systemd-runtime',
|
|
466
|
+
});
|
|
467
|
+
} finally {
|
|
468
|
+
await rm(fixture.tempDir, { recursive: true, force: true });
|
|
469
|
+
}
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
test('Linux real install waits for delayed user systemd runtime during fallback', async () => {
|
|
473
|
+
const fixture = await createLinuxFixtureApp();
|
|
474
|
+
const configFile = join(fixture.tempDir, 'client-config.json');
|
|
475
|
+
const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
|
|
476
|
+
const installRecordFile = join(fixture.tempDir, 'install.json');
|
|
477
|
+
const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
|
|
478
|
+
const calls: string[] = [];
|
|
479
|
+
|
|
480
|
+
try {
|
|
481
|
+
const output = await install({
|
|
482
|
+
realAppPath: fixture.appPath,
|
|
483
|
+
yes: true,
|
|
484
|
+
platform: 'linux',
|
|
485
|
+
arch: process.arch,
|
|
486
|
+
runtimeFile: fixture.runtimeFile,
|
|
487
|
+
backupDir: fixture.backupDir,
|
|
488
|
+
installRecordFile,
|
|
489
|
+
cursorExtensionsDir,
|
|
490
|
+
clientConfigFile: configFile,
|
|
491
|
+
linuxLauncherFile: launcherFile,
|
|
492
|
+
compatEntries: [fixture.compatEntry],
|
|
493
|
+
startDetachedService: async () => {
|
|
494
|
+
calls.push('detached');
|
|
495
|
+
throw new Error('Detached service failed to become healthy');
|
|
496
|
+
},
|
|
497
|
+
installUserAutostart: async (options) => {
|
|
498
|
+
calls.push('autostart');
|
|
499
|
+
setTimeout(() => {
|
|
500
|
+
void writeRuntimeInfo(
|
|
501
|
+
{ host: '127.0.0.1', port: 56394, runtimeId: 'delayed-systemd-runtime' },
|
|
502
|
+
{ runtimeFile: options.runtimeFile },
|
|
503
|
+
);
|
|
504
|
+
}, 100);
|
|
505
|
+
return { state: 'installed' as const };
|
|
506
|
+
},
|
|
507
|
+
fetchHealth: async (url) => {
|
|
508
|
+
calls.push(`health:${url}`);
|
|
509
|
+
return { ok: true, healthy: true };
|
|
510
|
+
},
|
|
511
|
+
});
|
|
512
|
+
|
|
513
|
+
assert.match(output, /service: running 127\.0\.0\.1:56394/);
|
|
514
|
+
assert.match(output, /autostart: installed/);
|
|
515
|
+
assert.match(output, /health: ok/);
|
|
516
|
+
assert.deepEqual(await readRuntimeInfo({ runtimeFile: fixture.runtimeFile }), {
|
|
517
|
+
host: '127.0.0.1',
|
|
518
|
+
port: 56394,
|
|
519
|
+
runtimeId: 'delayed-systemd-runtime',
|
|
520
|
+
});
|
|
521
|
+
assert.deepEqual(calls.slice(0, 3), [
|
|
522
|
+
'detached',
|
|
523
|
+
'autostart',
|
|
524
|
+
'health:http://127.0.0.1:56394/health',
|
|
525
|
+
]);
|
|
526
|
+
} finally {
|
|
527
|
+
await rm(fixture.tempDir, { recursive: true, force: true });
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
|
|
353
531
|
test('real-mode install writes install record and reports real mode', async () => {
|
|
354
532
|
const fixture = await createFixtureApp();
|
|
355
533
|
const installRecordFile = join(fixture.tempDir, 'install.json');
|
|
@@ -370,6 +548,7 @@ test('real-mode install writes install record and reports real mode', async () =
|
|
|
370
548
|
});
|
|
371
549
|
|
|
372
550
|
assert.match(output, /mode: real/);
|
|
551
|
+
assert.match(output, /takeover-plan: cursor-3\.5-mac-agent-f-workbench-p-l0/);
|
|
373
552
|
assert.match(output, /patch: applied/);
|
|
374
553
|
assert.match(output, /install-record: recorded/);
|
|
375
554
|
assert.doesNotMatch(output, /trial: recorded/);
|
|
@@ -380,6 +559,7 @@ test('real-mode install writes install record and reports real mode', async () =
|
|
|
380
559
|
assert.equal(record.mode, 'real');
|
|
381
560
|
assert.equal(record.appPath, fixture.appPath);
|
|
382
561
|
assert.equal(record.cursorVersion, '3.5.38');
|
|
562
|
+
assert.equal(record.takeoverPlanId, 'cursor-3.5-mac-agent-f-workbench-p-l0');
|
|
383
563
|
assert.equal(record.extensionInstallPath, extensionInstallPath);
|
|
384
564
|
assert.equal(record.extensionLinkedPath, linkedExtensionPathForDir(cursorExtensionsDir));
|
|
385
565
|
assert.equal(record.lastOperation, 'install');
|
|
@@ -393,6 +573,7 @@ test('real-mode install rolls back install record after health failure', async (
|
|
|
393
573
|
const fixture = await createFixtureApp();
|
|
394
574
|
const installRecordFile = join(fixture.tempDir, 'install.json');
|
|
395
575
|
const extensionInstallPath = join(fixture.tempDir, 'extensions/cursor-pool-status');
|
|
576
|
+
const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
|
|
396
577
|
|
|
397
578
|
try {
|
|
398
579
|
await assert.rejects(
|
|
@@ -403,6 +584,7 @@ test('real-mode install rolls back install record after health failure', async (
|
|
|
403
584
|
backupDir: fixture.backupDir,
|
|
404
585
|
installRecordFile,
|
|
405
586
|
extensionInstallPath,
|
|
587
|
+
cursorExtensionsDir,
|
|
406
588
|
compatEntries: [fixture.compatEntry],
|
|
407
589
|
stopServiceAfterInstall: true,
|
|
408
590
|
fetchHealth: async () => ({ ok: false, healthy: false }),
|
|
@@ -421,6 +603,7 @@ test('real-mode install requires confirmation when yes is missing', async () =>
|
|
|
421
603
|
const originalTargetContent = await readFile(fixture.targetPath, 'utf8');
|
|
422
604
|
const installRecordFile = join(fixture.tempDir, 'install.json');
|
|
423
605
|
const extensionInstallPath = join(fixture.tempDir, 'extensions/cursor-pool-status');
|
|
606
|
+
const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
|
|
424
607
|
|
|
425
608
|
try {
|
|
426
609
|
await assert.rejects(
|
|
@@ -431,6 +614,7 @@ test('real-mode install requires confirmation when yes is missing', async () =>
|
|
|
431
614
|
backupDir: fixture.backupDir,
|
|
432
615
|
installRecordFile,
|
|
433
616
|
extensionInstallPath,
|
|
617
|
+
cursorExtensionsDir,
|
|
434
618
|
compatEntries: [fixture.compatEntry],
|
|
435
619
|
stopServiceAfterInstall: true,
|
|
436
620
|
}),
|
|
@@ -469,6 +653,7 @@ test('install links extension into an explicit Cursor extensions directory', asy
|
|
|
469
653
|
assert.equal(await getLinkedExtensionState(linkedPath), 'linked');
|
|
470
654
|
|
|
471
655
|
const trialRecord = await readTrialRecord(fixture.appPath, { trialRecordDir });
|
|
656
|
+
assert.equal(trialRecord?.takeoverPlanId, 'cursor-3.5-mac-agent-f-workbench-p-l0');
|
|
472
657
|
assert.equal(trialRecord?.extensionState, 'linked');
|
|
473
658
|
assert.equal(trialRecord?.extensionInstallPath, extensionInstallPath);
|
|
474
659
|
assert.equal(trialRecord?.extensionLinkedPath, linkedPath);
|
package/test/repair.test.ts
CHANGED
|
@@ -89,6 +89,7 @@ async function createFixtureApp() {
|
|
|
89
89
|
cursorVersion: '3.5.38',
|
|
90
90
|
cursorCommit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
91
91
|
supportStatus: 'supported',
|
|
92
|
+
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
92
93
|
targetRelativePath,
|
|
93
94
|
expectedSha256: createHash('sha256').update(targetContent).digest('hex'),
|
|
94
95
|
structureSignature: 'fixture',
|
|
@@ -6,10 +6,19 @@ import { fileURLToPath } from 'node:url';
|
|
|
6
6
|
import test from 'node:test';
|
|
7
7
|
import { readRuntimeInfo } from '../../service/src/runtime';
|
|
8
8
|
import { startServer } from '../../service/src/server';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_DETACHED_SERVICE_STARTUP_TIMEOUT_MS,
|
|
11
|
+
startDetachedService,
|
|
12
|
+
stopRuntimeService,
|
|
13
|
+
waitForRuntimeHealth,
|
|
14
|
+
} from '../src/serviceProcess';
|
|
10
15
|
|
|
11
16
|
const cliRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
|
|
12
17
|
|
|
18
|
+
test('default detached service startup timeout allows slow Linux VMs', () => {
|
|
19
|
+
assert.equal(DEFAULT_DETACHED_SERVICE_STARTUP_TIMEOUT_MS, 30_000);
|
|
20
|
+
});
|
|
21
|
+
|
|
13
22
|
test('startDetachedService starts a service discoverable by runtime file', async () => {
|
|
14
23
|
const tempDir = await mkdtemp(join(tmpdir(), 'cursor-pool-detached-service-'));
|
|
15
24
|
const runtimeFile = join(tempDir, 'runtime.json');
|
package/test/status.test.ts
CHANGED
|
@@ -136,6 +136,7 @@ async function createFixtureApp() {
|
|
|
136
136
|
cursorVersion: '3.5.38',
|
|
137
137
|
cursorCommit: '009bb5a3600dd98fe1c1f25798f767f686e14750',
|
|
138
138
|
supportStatus: 'supported',
|
|
139
|
+
takeoverPlanId: 'cursor-3.6-mac-agent-c-workbench-h-uv',
|
|
139
140
|
targetRelativePath,
|
|
140
141
|
expectedSha256: createHash('sha256').update(targetContent).digest('hex'),
|
|
141
142
|
structureSignature: 'fixture',
|