Skip to content

Commit fbb8e60

Browse files
devswhae2e
andauthored
fix(cursor): report missing cursor agent correctly (#5)
Co-authored-by: e2e <e2e@example.com>
1 parent a22b5a7 commit fbb8e60

2 files changed

Lines changed: 67 additions & 6 deletions

File tree

‎server/modules/providers/list/cursor/cursor-auth.provider.ts‎

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,30 @@ type CursorLoginStatus = {
1010
error?: string;
1111
};
1212

13+
type CursorVersionProbe = typeof spawn.sync;
14+
15+
export const isCursorAgentInstalled = (
16+
runVersionProbe: CursorVersionProbe = spawn.sync,
17+
): boolean => {
18+
try {
19+
const result = runVersionProbe('cursor-agent', ['--version'], {
20+
stdio: 'ignore',
21+
timeout: 5000,
22+
});
23+
return !result.error && result.status === 0;
24+
} catch {
25+
return false;
26+
}
27+
};
28+
1329
export class CursorProviderAuth implements IProviderAuth {
30+
constructor(private readonly runVersionProbe: CursorVersionProbe = spawn.sync) {}
31+
1432
/**
1533
* Checks whether the cursor-agent CLI is available on this host.
1634
*/
1735
private checkInstalled(): boolean {
18-
try {
19-
spawn.sync('cursor-agent', ['--version'], { stdio: 'ignore', timeout: 5000 });
20-
return true;
21-
} catch {
22-
return false;
23-
}
36+
return isCursorAgentInstalled(this.runVersionProbe);
2437
}
2538

2639
/**
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import assert from 'node:assert/strict';
2+
import test from 'node:test';
3+
4+
import spawn from 'cross-spawn';
5+
6+
import {
7+
CursorProviderAuth,
8+
isCursorAgentInstalled,
9+
} from '@/modules/providers/list/cursor/cursor-auth.provider.js';
10+
11+
const probeResult = (
12+
overrides: Record<string, unknown>,
13+
): ReturnType<typeof spawn.sync> => ({
14+
pid: 123,
15+
output: [null, null, null],
16+
stdout: null,
17+
stderr: null,
18+
status: 0,
19+
signal: null,
20+
...overrides,
21+
} as unknown as ReturnType<typeof spawn.sync>);
22+
23+
const probe = (result: ReturnType<typeof spawn.sync>) => (
24+
(() => result) as typeof spawn.sync
25+
);
26+
27+
test('cursor installation probe accepts a successful version command', () => {
28+
assert.equal(isCursorAgentInstalled(probe(probeResult({ status: 0 }))), true);
29+
});
30+
31+
test('cursor installation probe rejects a non-zero version command', () => {
32+
assert.equal(isCursorAgentInstalled(probe(probeResult({ status: 1 }))), false);
33+
});
34+
35+
test('cursor installation probe rejects ENOENT and reports the provider as missing', async () => {
36+
const missing = Object.assign(new Error('spawnSync cursor-agent ENOENT'), { code: 'ENOENT' });
37+
const runVersionProbe = probe(probeResult({ error: missing, status: null }));
38+
39+
assert.equal(isCursorAgentInstalled(runVersionProbe), false);
40+
assert.deepEqual(await new CursorProviderAuth(runVersionProbe).getStatus(), {
41+
installed: false,
42+
provider: 'cursor',
43+
authenticated: false,
44+
email: null,
45+
method: null,
46+
error: 'Cursor CLI is not installed',
47+
});
48+
});

0 commit comments

Comments
 (0)