@cursorpool-dev/cli 0.5.6 → 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.
Files changed (93) hide show
  1. package/node_modules/@cursor-pool/extension/dist/extension.js +1 -1
  2. package/node_modules/@cursor-pool/extension/package.json +3 -3
  3. package/node_modules/@cursor-pool/extension/src/api.ts +1 -1
  4. package/node_modules/@cursor-pool/extension/test/panel.test.ts +1 -1
  5. package/node_modules/@cursor-pool/patcher/package.json +2 -2
  6. package/node_modules/@cursor-pool/patcher/src/marker.ts +72 -3
  7. package/node_modules/@cursor-pool/patcher/src/workbenchAuthGateMarker.ts +128 -14
  8. package/node_modules/@cursor-pool/patcher/test/patchCursorAgentExec.test.ts +102 -7
  9. package/node_modules/@cursor-pool/patcher/test/patchCursorWorkbench.test.ts +193 -0
  10. package/node_modules/@cursor-pool/service/package.json +2 -2
  11. package/node_modules/@cursor-pool/service/src/server.ts +1 -0
  12. package/node_modules/@cursor-pool/service/test/server.test.ts +1 -0
  13. package/node_modules/@cursor-pool/shared/package.json +1 -1
  14. package/node_modules/@cursor-pool/shared/test/manifest.test.ts +6 -6
  15. package/node_modules/@esbuild/linux-x64/README.md +3 -0
  16. package/node_modules/@esbuild/linux-x64/bin/esbuild +0 -0
  17. package/node_modules/@esbuild/linux-x64/package.json +20 -0
  18. package/node_modules/esbuild/LICENSE.md +21 -0
  19. package/node_modules/esbuild/README.md +3 -0
  20. package/node_modules/esbuild/bin/esbuild +223 -0
  21. package/node_modules/esbuild/install.js +300 -0
  22. package/node_modules/esbuild/lib/main.d.ts +716 -0
  23. package/node_modules/esbuild/lib/main.js +2532 -0
  24. package/node_modules/esbuild/package.json +74 -0
  25. package/node_modules/tsx/LICENSE +21 -0
  26. package/node_modules/tsx/README.md +32 -0
  27. package/node_modules/tsx/dist/cjs/api/index.cjs +1 -0
  28. package/node_modules/tsx/dist/cjs/api/index.d.cts +35 -0
  29. package/node_modules/tsx/dist/cjs/api/index.d.mts +35 -0
  30. package/node_modules/tsx/dist/cjs/api/index.mjs +1 -0
  31. package/node_modules/tsx/dist/cjs/index.cjs +1 -0
  32. package/node_modules/tsx/dist/cjs/index.mjs +1 -0
  33. package/node_modules/tsx/dist/cli.cjs +54 -0
  34. package/node_modules/tsx/dist/cli.mjs +55 -0
  35. package/node_modules/tsx/dist/client-D3mGB526.cjs +1 -0
  36. package/node_modules/tsx/dist/client-D_mPDF5S.mjs +1 -0
  37. package/node_modules/tsx/dist/esm/api/index.cjs +1 -0
  38. package/node_modules/tsx/dist/esm/api/index.d.cts +35 -0
  39. package/node_modules/tsx/dist/esm/api/index.d.mts +35 -0
  40. package/node_modules/tsx/dist/esm/api/index.mjs +1 -0
  41. package/node_modules/tsx/dist/esm/index.cjs +1 -0
  42. package/node_modules/tsx/dist/esm/index.mjs +1 -0
  43. package/node_modules/tsx/dist/get-pipe-path-D4YM6rQt.cjs +1 -0
  44. package/node_modules/tsx/dist/get-pipe-path-_tAJyU_v.mjs +1 -0
  45. package/node_modules/tsx/dist/index-BWFBUo6r.cjs +1 -0
  46. package/node_modules/tsx/dist/index-D9F1FXzN.cjs +14 -0
  47. package/node_modules/tsx/dist/index-XurvG3JN.mjs +14 -0
  48. package/node_modules/tsx/dist/index-gbaejti9.mjs +1 -0
  49. package/node_modules/tsx/dist/lexer-DQCqS3nf.mjs +3 -0
  50. package/node_modules/tsx/dist/lexer-DgIbo0BU.cjs +3 -0
  51. package/node_modules/tsx/dist/loader.cjs +1 -0
  52. package/node_modules/tsx/dist/loader.mjs +1 -0
  53. package/node_modules/tsx/dist/node-features-B9BBLzwu.mjs +1 -0
  54. package/node_modules/tsx/dist/node-features-CQLdkVE6.cjs +1 -0
  55. package/node_modules/tsx/dist/package-CGdS2_oX.cjs +1 -0
  56. package/node_modules/tsx/dist/package-DyJMwVU5.mjs +1 -0
  57. package/node_modules/tsx/dist/patch-repl.cjs +1 -0
  58. package/node_modules/tsx/dist/patch-repl.mjs +1 -0
  59. package/node_modules/tsx/dist/preflight.cjs +1 -0
  60. package/node_modules/tsx/dist/preflight.mjs +1 -0
  61. package/node_modules/tsx/dist/register-BOkp8V6j.cjs +10 -0
  62. package/node_modules/tsx/dist/register-BnTWPeIB.mjs +10 -0
  63. package/node_modules/tsx/dist/register-CHVGxKtC.cjs +2 -0
  64. package/node_modules/tsx/dist/register-D_B8UL5H.mjs +2 -0
  65. package/node_modules/tsx/dist/repl.cjs +3 -0
  66. package/node_modules/tsx/dist/repl.mjs +3 -0
  67. package/node_modules/tsx/dist/require-CjvaJWEr.cjs +1 -0
  68. package/node_modules/tsx/dist/require-DzmC1hVr.mjs +1 -0
  69. package/node_modules/tsx/dist/suppress-warnings.cjs +1 -0
  70. package/node_modules/tsx/dist/suppress-warnings.mjs +1 -0
  71. package/node_modules/tsx/dist/temporary-directory-B83uKxJF.cjs +1 -0
  72. package/node_modules/tsx/dist/temporary-directory-BDDVQOvU.mjs +1 -0
  73. package/node_modules/tsx/dist/types-Cxp8y2TL.d.ts +5 -0
  74. package/node_modules/tsx/package.json +67 -0
  75. package/package.json +9 -6
  76. package/src/autostart.ts +5 -1
  77. package/src/compat.ts +103 -29
  78. package/src/cursor.ts +59 -3
  79. package/src/extensionBundle.ts +1 -1
  80. package/src/extensionLink.ts +3 -3
  81. package/src/install.ts +118 -19
  82. package/src/platform.ts +3 -3
  83. package/src/repair.ts +2 -1
  84. package/src/serviceProcess.ts +2 -1
  85. package/src/trial.ts +2 -2
  86. package/test/autostart.test.ts +23 -2
  87. package/test/compat.test.ts +108 -9
  88. package/test/cursor-pool-bin.test.ts +1 -0
  89. package/test/cursor.test.ts +60 -1
  90. package/test/extensionLink.test.ts +24 -1
  91. package/test/install.test.ts +127 -2
  92. package/test/serviceProcess.test.ts +10 -1
  93. package/test/trial.test.ts +15 -1
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { mkdir, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
4
+ import { isAbsolute, join, relative } from 'node:path';
5
5
  import test from 'node:test';
6
6
  import {
7
7
  getLinkedExtensionState,
@@ -123,6 +123,29 @@ test('linkExtensionBundle refreshes Cursor extensions index with runtime extensi
123
123
  }
124
124
  });
125
125
 
126
+ test('linkExtensionBundle writes an absolute linked extension location for relative cursor extensions dir', async () => {
127
+ const tempDir = await mkdtemp(join(process.cwd(), '.cursor-pool-extension-link-relative-'));
128
+ const sourceBundlePath = await createSourceBundle(tempDir);
129
+ const cursorExtensionsDir = join(tempDir, 'Extensions');
130
+ const relativeCursorExtensionsDir = relative(process.cwd(), cursorExtensionsDir);
131
+ await mkdir(cursorExtensionsDir, { recursive: true });
132
+ await writeFile(join(cursorExtensionsDir, 'extensions.json'), '[]\n', 'utf8');
133
+
134
+ try {
135
+ const result = await linkExtensionBundle({
136
+ sourceBundlePath,
137
+ cursorExtensionsDir: relativeCursorExtensionsDir,
138
+ });
139
+ const index = JSON.parse(await readFile(join(cursorExtensionsDir, 'extensions.json'), 'utf8'));
140
+
141
+ assert.equal(isAbsolute(result.linkedPath), true);
142
+ assert.equal(isAbsolute(index.at(-1).location.path), true);
143
+ assert.equal(index.at(-1).location.path, result.linkedPath);
144
+ } finally {
145
+ await rm(tempDir, { recursive: true, force: true });
146
+ }
147
+ });
148
+
126
149
  test('linkExtensionBundle reports missing when source bundle is absent', async () => {
127
150
  const tempDir = await mkdtemp(join(tmpdir(), 'cursor-pool-extension-link-missing-'));
128
151
  const cursorExtensionsDir = join(tempDir, 'Extensions');
@@ -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';
@@ -225,6 +225,7 @@ test('install reports Cursor version, simulated extension, service, patch, and h
225
225
 
226
226
  test('install detects Linux Cursor AppImage layout under usr/share/cursor', async () => {
227
227
  const fixture = await createLinuxFixtureApp();
228
+ const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
228
229
 
229
230
  try {
230
231
  const output = await install({
@@ -235,14 +236,20 @@ test('install detects Linux Cursor AppImage layout under usr/share/cursor', asyn
235
236
  backupDir: fixture.backupDir,
236
237
  trialRecordDir: join(fixture.tempDir, 'trials'),
237
238
  extensionInstallPath: join(fixture.tempDir, 'extensions/cursor-pool-status'),
239
+ linuxLauncherFile: launcherFile,
238
240
  compatEntries: [fixture.compatEntry],
239
241
  stopServiceAfterInstall: true,
240
242
  });
241
243
 
242
244
  assert.match(output, /Cursor 3\.6\.31/);
243
245
  assert.match(output, /patch: applied/);
246
+ assert.match(output, /launcher: .*cursor-pool-cursor/);
244
247
  assert.match(output, /health: ok/);
245
248
  assert.match(await readFile(fixture.targetPath, 'utf8'), new RegExp(CURSOR_POOL_PATCH_MARKER));
249
+ const launcher = await readFile(launcherFile, 'utf8');
250
+ assert.match(launcher, /AppRun/);
251
+ assert.match(launcher, /--no-sandbox/);
252
+ assert.equal((await stat(launcherFile)).mode & 0o111, 0o111);
246
253
  } finally {
247
254
  await rm(fixture.tempDir, { recursive: true, force: true });
248
255
  }
@@ -350,6 +357,124 @@ test('install persists API base URL and installs user autostart for real client
350
357
  }
351
358
  });
352
359
 
360
+ test('Linux real install falls back to user systemd when detached service startup is unhealthy', async () => {
361
+ const fixture = await createLinuxFixtureApp();
362
+ const configFile = join(fixture.tempDir, 'client-config.json');
363
+ const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
364
+ const installRecordFile = join(fixture.tempDir, 'install.json');
365
+ const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
366
+ const calls: string[] = [];
367
+
368
+ try {
369
+ const output = await install({
370
+ realAppPath: fixture.appPath,
371
+ yes: true,
372
+ platform: 'linux',
373
+ arch: process.arch,
374
+ runtimeFile: fixture.runtimeFile,
375
+ backupDir: fixture.backupDir,
376
+ installRecordFile,
377
+ cursorExtensionsDir,
378
+ clientConfigFile: configFile,
379
+ linuxLauncherFile: launcherFile,
380
+ compatEntries: [fixture.compatEntry],
381
+ startDetachedService: async () => {
382
+ calls.push('detached');
383
+ throw new Error('Detached service failed to become healthy');
384
+ },
385
+ installUserAutostart: async (options) => {
386
+ calls.push('autostart');
387
+ await writeRuntimeInfo(
388
+ { host: '127.0.0.1', port: 56393, runtimeId: 'systemd-runtime' },
389
+ { runtimeFile: options.runtimeFile },
390
+ );
391
+ return { state: 'installed' as const };
392
+ },
393
+ fetchHealth: async (url) => {
394
+ calls.push(`health:${url}`);
395
+ return { ok: true, healthy: true };
396
+ },
397
+ });
398
+
399
+ assert.deepEqual(calls, [
400
+ 'detached',
401
+ 'autostart',
402
+ 'health:http://127.0.0.1:56393/health',
403
+ 'health:http://127.0.0.1:56393/health',
404
+ ]);
405
+ assert.match(output, /mode: real/);
406
+ assert.match(output, /service: running 127\.0\.0\.1:56393/);
407
+ assert.match(output, /autostart: installed/);
408
+ assert.match(output, /health: ok/);
409
+ assert.deepEqual(await readRuntimeInfo({ runtimeFile: fixture.runtimeFile }), {
410
+ host: '127.0.0.1',
411
+ port: 56393,
412
+ runtimeId: 'systemd-runtime',
413
+ });
414
+ } finally {
415
+ await rm(fixture.tempDir, { recursive: true, force: true });
416
+ }
417
+ });
418
+
419
+ test('Linux real install waits for delayed user systemd runtime during fallback', async () => {
420
+ const fixture = await createLinuxFixtureApp();
421
+ const configFile = join(fixture.tempDir, 'client-config.json');
422
+ const cursorExtensionsDir = join(fixture.tempDir, 'real-extensions');
423
+ const installRecordFile = join(fixture.tempDir, 'install.json');
424
+ const launcherFile = join(fixture.tempDir, 'bin/cursor-pool-cursor');
425
+ const calls: string[] = [];
426
+
427
+ try {
428
+ const output = await install({
429
+ realAppPath: fixture.appPath,
430
+ yes: true,
431
+ platform: 'linux',
432
+ arch: process.arch,
433
+ runtimeFile: fixture.runtimeFile,
434
+ backupDir: fixture.backupDir,
435
+ installRecordFile,
436
+ cursorExtensionsDir,
437
+ clientConfigFile: configFile,
438
+ linuxLauncherFile: launcherFile,
439
+ compatEntries: [fixture.compatEntry],
440
+ startDetachedService: async () => {
441
+ calls.push('detached');
442
+ throw new Error('Detached service failed to become healthy');
443
+ },
444
+ installUserAutostart: async (options) => {
445
+ calls.push('autostart');
446
+ setTimeout(() => {
447
+ void writeRuntimeInfo(
448
+ { host: '127.0.0.1', port: 56394, runtimeId: 'delayed-systemd-runtime' },
449
+ { runtimeFile: options.runtimeFile },
450
+ );
451
+ }, 100);
452
+ return { state: 'installed' as const };
453
+ },
454
+ fetchHealth: async (url) => {
455
+ calls.push(`health:${url}`);
456
+ return { ok: true, healthy: true };
457
+ },
458
+ });
459
+
460
+ assert.match(output, /service: running 127\.0\.0\.1:56394/);
461
+ assert.match(output, /autostart: installed/);
462
+ assert.match(output, /health: ok/);
463
+ assert.deepEqual(await readRuntimeInfo({ runtimeFile: fixture.runtimeFile }), {
464
+ host: '127.0.0.1',
465
+ port: 56394,
466
+ runtimeId: 'delayed-systemd-runtime',
467
+ });
468
+ assert.deepEqual(calls.slice(0, 3), [
469
+ 'detached',
470
+ 'autostart',
471
+ 'health:http://127.0.0.1:56394/health',
472
+ ]);
473
+ } finally {
474
+ await rm(fixture.tempDir, { recursive: true, force: true });
475
+ }
476
+ });
477
+
353
478
  test('real-mode install writes install record and reports real mode', async () => {
354
479
  const fixture = await createFixtureApp();
355
480
  const installRecordFile = join(fixture.tempDir, 'install.json');
@@ -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 { startDetachedService, stopRuntimeService, waitForRuntimeHealth } from '../src/serviceProcess';
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');
@@ -1,7 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { mkdir, mkdtemp, readFile, rm, symlink } from 'node:fs/promises';
3
3
  import { tmpdir } from 'node:os';
4
- import { join } from 'node:path';
4
+ import { join, relative, resolve } from 'node:path';
5
5
  import test from 'node:test';
6
6
  import {
7
7
  assertDisposableCursorAppPath,
@@ -55,6 +55,20 @@ test('assertDisposableCursorAppPath accepts a disposable app copy path', () => {
55
55
  );
56
56
  });
57
57
 
58
+ test('assertDisposableCursorAppPath normalizes relative disposable app paths to absolute paths', async () => {
59
+ const tempDir = await mkdtemp(join(process.cwd(), '.cursor-pool-relative-app-path-'));
60
+ const appPath = join(tempDir, 'Cursor-Trial.app');
61
+
62
+ try {
63
+ await mkdir(appPath, { recursive: true });
64
+ const relativeAppPath = relative(process.cwd(), appPath);
65
+
66
+ assert.equal(assertDisposableCursorAppPath(relativeAppPath), resolve(appPath));
67
+ } finally {
68
+ await rm(tempDir, { recursive: true, force: true });
69
+ }
70
+ });
71
+
58
72
  test('assertDisposableCursorAppPath rejects non app bundle paths', () => {
59
73
  assert.throws(
60
74
  () => assertDisposableCursorAppPath('/Users/example/Desktop/Cursor-Pool-Trial'),