forked from nexu-io/open-design
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcursor-agent.ts
More file actions
106 lines (100 loc) · 3.91 KB
/
Copy pathcursor-agent.ts
File metadata and controls
106 lines (100 loc) · 3.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { DEFAULT_MODEL_OPTION } from './shared.js';
import { agentCapabilities } from '../capabilities.js';
import type { RuntimeAgentDef } from '../types.js';
import type { RuntimeModelOption } from '../types.js';
export function parseCursorAgentModels(stdout: string): RuntimeModelOption[] | null {
const lines = String(stdout || '')
.split('\n')
.map((line) => line.trim())
.filter((line) => line.length > 0 && !line.startsWith('#'));
if (lines.length === 0) return null;
const out = [DEFAULT_MODEL_OPTION];
const seen = new Set<string>([DEFAULT_MODEL_OPTION.id]);
for (const line of lines) {
if (/^(available models|models)$/i.test(line)) continue;
const match = line.match(/^([A-Za-z0-9][A-Za-z0-9._/:@-]*)(?:\s+-\s+(.+))?$/);
if (!match) continue;
const id = match[1];
if (!id || seen.has(id)) continue;
seen.add(id);
const label = match[2]?.trim() || id;
out.push({ id, label });
}
return out.length > 1 ? out : null;
}
export const cursorAgentDef = {
id: 'cursor-agent',
name: 'Cursor Agent',
bin: 'cursor-agent',
versionArgs: ['--version'],
helpArgs: ['--help'],
capabilityFlags: {
// Flag string -> capability key. After probing `--help`, detection sets
// `agentCapabilities['cursor-agent'][key] = true` for each substring it
// finds. `--trust` is only honored in `-p`/headless mode and only exists
// on newer cursor-agent builds; older installs reject it with
// "unknown option '--trust'" and exit 1, which kills Test and task
// execution (issue #4461). Gate on the probe like claude/codebuddy do.
'--trust': 'trust',
},
// `cursor-agent models` prints account-bound model ids per line. When
// the user isn't authed it prints "No models available for this
// account." — that's not a model list, so we detect it and fall back.
listModels: {
args: ['models'],
timeoutMs: 5000,
parse: (stdout) => {
const trimmed = String(stdout || '').trim();
if (!trimmed || /no models available/i.test(trimmed)) return null;
return parseCursorAgentModels(trimmed);
},
},
fallbackModels: [
DEFAULT_MODEL_OPTION,
{ id: 'auto', label: 'auto' },
{ id: 'sonnet-4', label: 'sonnet-4' },
{ id: 'sonnet-4-thinking', label: 'sonnet-4-thinking' },
{ id: 'gpt-5', label: 'gpt-5' },
],
// Cursor Agent does not use `-` as a "read prompt from stdin" sentinel.
// Passing it makes the CLI treat the dash as the literal user prompt,
// which then surfaces as "your message only contains '-'". Keep stdin
// piped for prompt delivery, but do not append a fake prompt arg.
buildArgs: (
_prompt,
_imagePaths,
_extra,
options = {},
runtimeContext = {},
) => {
const caps = agentCapabilities.get('cursor-agent') || {};
const args = [];
args.push(
'--print',
'--output-format',
'stream-json',
'--stream-partial-output',
'--force',
);
// `--trust` grants workspace trust in headless runs, but only newer
// cursor-agent builds accept it; older ones exit 1 with "unknown option"
// (issue #4461). Pass it only when the `--help` probe saw it.
if (caps.trust) {
args.push('--trust');
}
if (runtimeContext.cwd) {
args.push('--workspace', runtimeContext.cwd);
}
if (options.model && options.model !== 'default') {
args.push('--model', options.model);
}
return args;
},
promptViaStdin: true,
streamFormat: 'json-event-stream',
eventParser: 'cursor-agent',
// `cursor-agent status` is a cheap, side-effect-free auth check. Declaring
// it here is what makes detection surface an "auth required" badge for
// Cursor Agent (the generalized probe only runs for adapters that opt in).
authProbe: { args: ['status'], timeoutMs: 5000 },
} satisfies RuntimeAgentDef;