@agent-deck/cli 1.11.9 → 2.1.0
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/dist/agent-harness.d.ts +9 -2
- package/dist/agent-harness.d.ts.map +1 -1
- package/dist/agent-harness.js +90 -23
- package/dist/agent-harness.js.map +1 -1
- package/dist/codex-plugin.d.ts +27 -0
- package/dist/codex-plugin.d.ts.map +1 -1
- package/dist/codex-plugin.js +111 -6
- package/dist/codex-plugin.js.map +1 -1
- package/dist/daemon-logs.d.ts +1 -1
- package/dist/daemon-logs.d.ts.map +1 -1
- package/dist/daemon-logs.js +49 -1
- package/dist/daemon-logs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +97 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp-bridge.d.ts +83 -1
- package/dist/mcp-bridge.d.ts.map +1 -1
- package/dist/mcp-bridge.js +252 -7
- package/dist/mcp-bridge.js.map +1 -1
- package/dist/mcp-config.d.ts +13 -1
- package/dist/mcp-config.d.ts.map +1 -1
- package/dist/mcp-config.js +49 -1
- package/dist/mcp-config.js.map +1 -1
- package/dist/muse-skills/agent-deck-playbooks/SKILL.md +24 -0
- package/dist/muse-skills/agent-deck-run/SKILL.md +69 -0
- package/dist/muse-skills/agent-deck-session/SKILL.md +59 -0
- package/dist/muse-skills/agent-deck-setup/SKILL.md +28 -0
- package/dist/muse-skills.d.ts +42 -0
- package/dist/muse-skills.d.ts.map +1 -0
- package/dist/muse-skills.js +149 -0
- package/dist/muse-skills.js.map +1 -0
- package/dist/run-adapter.d.ts +100 -0
- package/dist/run-adapter.d.ts.map +1 -0
- package/dist/run-adapter.js +73 -0
- package/dist/run-adapter.js.map +1 -0
- package/dist/run-claude.d.ts +41 -0
- package/dist/run-claude.d.ts.map +1 -0
- package/dist/run-claude.js +91 -0
- package/dist/run-claude.js.map +1 -0
- package/dist/run-codex.d.ts +75 -0
- package/dist/run-codex.d.ts.map +1 -0
- package/dist/run-codex.js +337 -0
- package/dist/run-codex.js.map +1 -0
- package/dist/run-cursor.d.ts +79 -0
- package/dist/run-cursor.d.ts.map +1 -0
- package/dist/run-cursor.js +455 -0
- package/dist/run-cursor.js.map +1 -0
- package/dist/run-detach.d.ts +36 -0
- package/dist/run-detach.d.ts.map +1 -0
- package/dist/run-detach.js +233 -0
- package/dist/run-detach.js.map +1 -0
- package/dist/run-muse.d.ts +127 -0
- package/dist/run-muse.d.ts.map +1 -0
- package/dist/run-muse.js +499 -0
- package/dist/run-muse.js.map +1 -0
- package/dist/run-status.d.ts +62 -0
- package/dist/run-status.d.ts.map +1 -0
- package/dist/run-status.js +552 -0
- package/dist/run-status.js.map +1 -0
- package/dist/run.d.ts +191 -0
- package/dist/run.d.ts.map +1 -0
- package/dist/run.js +680 -0
- package/dist/run.js.map +1 -0
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +51 -10
- package/dist/setup.js.map +1 -1
- package/dist/terminal-style.d.ts +9 -0
- package/dist/terminal-style.d.ts.map +1 -0
- package/dist/terminal-style.js +34 -0
- package/dist/terminal-style.js.map +1 -0
- package/dist/use.d.ts +1 -1
- package/dist/use.d.ts.map +1 -1
- package/dist/use.js +16 -15
- package/dist/use.js.map +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CURSOR_OUTPUT_FORMAT = exports.CURSOR_JSON_VERSION_NOTE = void 0;
|
|
7
|
+
exports.resolveCursorBin = resolveCursorBin;
|
|
8
|
+
exports.assertSafeCursorResumeId = assertSafeCursorResumeId;
|
|
9
|
+
exports.buildCursorArgv = buildCursorArgv;
|
|
10
|
+
exports.defaultCursorProbe = defaultCursorProbe;
|
|
11
|
+
exports.defaultCursorSpawn = defaultCursorSpawn;
|
|
12
|
+
exports.isCursorStatusAuthenticated = isCursorStatusAuthenticated;
|
|
13
|
+
exports.cursorEventsFromOutput = cursorEventsFromOutput;
|
|
14
|
+
exports.createCursorAdapter = createCursorAdapter;
|
|
15
|
+
/**
|
|
16
|
+
* Cursor adapter for `agent-deck run` (NOT-406).
|
|
17
|
+
*
|
|
18
|
+
* Drives `cursor-agent -p --trust --output-format json` (start and resume, the
|
|
19
|
+
* latter adding `--resume <chatId>`) as a child process and maps the single
|
|
20
|
+
* result object onto normalized events. Verified against cursor-agent
|
|
21
|
+
* 2026.10.01 (`cursor-agent --help`, `cursor-agent status --format json`):
|
|
22
|
+
*
|
|
23
|
+
* - Output format is single-shot `json`, not `stream-json`: the stream-json
|
|
24
|
+
* event shape is uncaptured (no incremental events were observed), while
|
|
25
|
+
* the owner's smoke test verified `json` returns a result object with
|
|
26
|
+
* `session_id`. Consequence: all log lines land when the process exits, so
|
|
27
|
+
* status polling shows no intermediate lines for Cursor.
|
|
28
|
+
* - The answer text is yielded as one `text` event (so the shared session
|
|
29
|
+
* receipt check sees it) followed by `result`; the full result object is
|
|
30
|
+
* the `result` payload.
|
|
31
|
+
* - Tool mapping: `readonly` passes no write-enabling flag; `edit` passes
|
|
32
|
+
* `--force`. `--yolo` (an alias for `--force`) is never passed and no
|
|
33
|
+
* option can select it; `--approve-mcps` is never passed (separate owner
|
|
34
|
+
* decision required).
|
|
35
|
+
* - Deck receipt is mandatory on start (not resume): a success whose output
|
|
36
|
+
* lacks a `◆ ... ·` display_summary line fails closed as `error`, because
|
|
37
|
+
* Cursor's global MCP entry is last-workspace-wins and a missing receipt
|
|
38
|
+
* would otherwise look like a correctly bound run. Resume is exempt (the
|
|
39
|
+
* harness prints the receipt on the first turn only).
|
|
40
|
+
* - `--force` means "allow commands unless explicitly denied" (auto-approval),
|
|
41
|
+
* and `-p` help says print mode "has access to all tools, including write
|
|
42
|
+
* and shell", so whether readonly truly cannot write is settled by the
|
|
43
|
+
* operator edit-vs-readonly test, not by the flags.
|
|
44
|
+
* - `--trust` is passed on every launch (the caller named --cwd explicitly)
|
|
45
|
+
* and recorded as `trustOverride: true` in meta.json — the existing meta
|
|
46
|
+
* field for "launch bypassed a client workspace-trust guard". Without it
|
|
47
|
+
* the CLI prints "Workspace Trust Required" with an empty success, so that
|
|
48
|
+
* string (and any empty result at exit 0) fails closed as `error`.
|
|
49
|
+
* - Signed-in preflight is `cursor-agent status --format json` (exit 0 even
|
|
50
|
+
* when signed out, so the output is parsed, not just the exit code), which
|
|
51
|
+
* makes no model call.
|
|
52
|
+
* - The prompt is passed after a `--` terminator (verified: `cursor-agent -p
|
|
53
|
+
* --trust --output-format json -- --help` treats `--help` as the prompt
|
|
54
|
+
* instead of printing help), so dash-leading prompts cannot be parsed as
|
|
55
|
+
* options. Resume ids starting with `-` fail closed in planStart.
|
|
56
|
+
*/
|
|
57
|
+
const node_child_process_1 = require("node:child_process");
|
|
58
|
+
const node_readline_1 = __importDefault(require("node:readline"));
|
|
59
|
+
exports.CURSOR_JSON_VERSION_NOTE = 'cursor-agent 2026.10.01';
|
|
60
|
+
/** Single-shot result object; stream-json incremental shape is unverified. */
|
|
61
|
+
exports.CURSOR_OUTPUT_FORMAT = 'json';
|
|
62
|
+
function resolveCursorBin() {
|
|
63
|
+
return process.env.CURSOR_BIN?.trim() || 'cursor-agent';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Resume ids are cursor chat ids (32-hex); a leading `-` is never legitimate
|
|
67
|
+
* and would be parsed as a cursor-agent option, so it fails closed in
|
|
68
|
+
* planStart and throws here. Belt and suspenders with the `--` placement
|
|
69
|
+
* below: this builder never emits a dash-leading id at all.
|
|
70
|
+
*/
|
|
71
|
+
function assertSafeCursorResumeId(resumeId) {
|
|
72
|
+
if (resumeId.startsWith('-')) {
|
|
73
|
+
throw new Error(`Invalid --resume id ${JSON.stringify(resumeId)}: session ids never start with '-'. ` +
|
|
74
|
+
'Pass the chat id printed as sessionId in a previous run log.');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Pure argv builder (everything after the `cursor-agent` binary):
|
|
79
|
+
* `-p --trust --output-format json [--force] [--resume <id>] -- <prompt>`.
|
|
80
|
+
* `--force` only for the edit profile; `--yolo` and `--approve-mcps` are
|
|
81
|
+
* never emitted. The `--` terminator keeps dash-leading prompts from being
|
|
82
|
+
* parsed as cursor-agent options.
|
|
83
|
+
*/
|
|
84
|
+
function buildCursorArgv(args) {
|
|
85
|
+
const argv = ['-p', '--trust', '--output-format', exports.CURSOR_OUTPUT_FORMAT];
|
|
86
|
+
if (args.tools === 'edit') {
|
|
87
|
+
argv.push('--force');
|
|
88
|
+
}
|
|
89
|
+
if (args.resumeId !== undefined) {
|
|
90
|
+
assertSafeCursorResumeId(args.resumeId);
|
|
91
|
+
argv.push('--resume', args.resumeId);
|
|
92
|
+
}
|
|
93
|
+
argv.push('--', args.prompt);
|
|
94
|
+
return argv;
|
|
95
|
+
}
|
|
96
|
+
function defaultCursorProbe(bin, argv) {
|
|
97
|
+
try {
|
|
98
|
+
const probed = (0, node_child_process_1.spawnSync)(bin, argv, { encoding: 'utf8', timeout: 15000 });
|
|
99
|
+
return { code: probed.status ?? 1, stdout: probed.stdout ?? '', stderr: probed.stderr ?? '' };
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return { code: 127, stdout: '', stderr: '' };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function defaultCursorSpawn(bin, argv, opts) {
|
|
106
|
+
const child = (0, node_child_process_1.spawn)(bin, argv, { cwd: opts.cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
107
|
+
let spawnError = null;
|
|
108
|
+
child.on('error', (error) => {
|
|
109
|
+
spawnError = error;
|
|
110
|
+
child.stdout?.destroy();
|
|
111
|
+
});
|
|
112
|
+
const stderrChunks = [];
|
|
113
|
+
child.stderr?.on('data', (chunk) => {
|
|
114
|
+
stderrChunks.push(Buffer.from(chunk));
|
|
115
|
+
});
|
|
116
|
+
async function* lines() {
|
|
117
|
+
const rl = node_readline_1.default.createInterface({ input: child.stdout });
|
|
118
|
+
try {
|
|
119
|
+
for await (const line of rl) {
|
|
120
|
+
yield line;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// The stdout stream is destroyed when the spawn itself fails; the
|
|
125
|
+
// spawn error below is the actionable failure.
|
|
126
|
+
}
|
|
127
|
+
if (spawnError) {
|
|
128
|
+
throw spawnError;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
const wait = () => new Promise((resolve) => {
|
|
132
|
+
let settled = false;
|
|
133
|
+
const done = (code) => {
|
|
134
|
+
if (settled) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
settled = true;
|
|
138
|
+
resolve({
|
|
139
|
+
code,
|
|
140
|
+
stderrTail: Buffer.concat(stderrChunks).toString('utf8').slice(-2000),
|
|
141
|
+
});
|
|
142
|
+
};
|
|
143
|
+
child.on('close', done);
|
|
144
|
+
child.on('error', () => done(127));
|
|
145
|
+
});
|
|
146
|
+
return { stdout: lines(), wait };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* `cursor-agent status --format json` exits 0 even when signed out
|
|
150
|
+
* (`{"status":"unauthenticated","isAuthenticated":false,...}`), so the
|
|
151
|
+
* output decides. The `isAuthenticated` boolean wins; the `status` string
|
|
152
|
+
* and a text fallback cover older shapes. Unknown output fails closed.
|
|
153
|
+
*/
|
|
154
|
+
function isCursorStatusAuthenticated(output) {
|
|
155
|
+
const trimmed = output.trim();
|
|
156
|
+
if (trimmed) {
|
|
157
|
+
try {
|
|
158
|
+
const parsed = JSON.parse(trimmed);
|
|
159
|
+
if (typeof parsed === 'object' && parsed !== null) {
|
|
160
|
+
const record = parsed;
|
|
161
|
+
if (typeof record.isAuthenticated === 'boolean') {
|
|
162
|
+
return record.isAuthenticated;
|
|
163
|
+
}
|
|
164
|
+
if (typeof record.status === 'string') {
|
|
165
|
+
const status = record.status.trim().toLowerCase();
|
|
166
|
+
if (status === 'authenticated') {
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
if (status === 'unauthenticated') {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// Fall through to the text heuristics below.
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
if (/not logged in|unauthenticated/i.test(trimmed)) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
return /logged in/i.test(trimmed);
|
|
183
|
+
}
|
|
184
|
+
function asRecord(value) {
|
|
185
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
186
|
+
? value
|
|
187
|
+
: null;
|
|
188
|
+
}
|
|
189
|
+
function nonEmptyString(value) {
|
|
190
|
+
return typeof value === 'string' && value ? value : null;
|
|
191
|
+
}
|
|
192
|
+
function firstString(record, keys) {
|
|
193
|
+
for (const key of keys) {
|
|
194
|
+
const value = nonEmptyString(record[key]);
|
|
195
|
+
if (value) {
|
|
196
|
+
return value;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
function stringArray(value) {
|
|
202
|
+
if (!Array.isArray(value)) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
return value.filter((entry) => typeof entry === 'string' && !!entry);
|
|
206
|
+
}
|
|
207
|
+
function toolNames(value) {
|
|
208
|
+
if (!Array.isArray(value)) {
|
|
209
|
+
return [];
|
|
210
|
+
}
|
|
211
|
+
const names = [];
|
|
212
|
+
for (const entry of value) {
|
|
213
|
+
if (typeof entry === 'string' && entry) {
|
|
214
|
+
names.push(entry);
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
const record = asRecord(entry);
|
|
218
|
+
if (!record) {
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
const name = nonEmptyString(record.name) ??
|
|
222
|
+
nonEmptyString(record.tool) ??
|
|
223
|
+
(nonEmptyString(record.command) ? `command:${record.command}`.slice(0, 200) : null);
|
|
224
|
+
if (name) {
|
|
225
|
+
names.push(name);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return names;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Map the single-shot `--output-format json` stdout onto normalized events:
|
|
232
|
+
* the result object's `session_id` becomes `sessionId`; the answer text
|
|
233
|
+
* becomes one `text` event; tool arrays become `tool` events; warning arrays
|
|
234
|
+
* become `notice` events; the full object becomes the `result` payload
|
|
235
|
+
* (subtype `success`, or `failed` when the object carries `error`,
|
|
236
|
+
* `is_error: true`, or a non-`success` subtype).
|
|
237
|
+
*
|
|
238
|
+
* Throws (so the shared run code marks the run `error`) on "Workspace Trust
|
|
239
|
+
* Required", on empty output at exit 0, on non-JSON output, on a result
|
|
240
|
+
* object with no answer text, tool call, or error content (a bare session
|
|
241
|
+
* id, including the resume-id fallback, is not content), and — on start
|
|
242
|
+
* only, not resume — on a success whose output lacks a `◆ ... ·` deck
|
|
243
|
+
* receipt line. Never returns an empty event list: success always ends with
|
|
244
|
+
* a `result` event.
|
|
245
|
+
*/
|
|
246
|
+
function cursorEventsFromOutput(stdout, opts = {}) {
|
|
247
|
+
if (stdout.includes('Workspace Trust Required')) {
|
|
248
|
+
throw new Error('cursor-agent reported "Workspace Trust Required": open the folder in Cursor and accept the workspace trust prompt, then retry.');
|
|
249
|
+
}
|
|
250
|
+
const trimmed = stdout.trim();
|
|
251
|
+
if (!trimmed) {
|
|
252
|
+
throw new Error('cursor-agent returned an empty result (exit 0): retry the run; if it persists, check `cursor-agent status` and re-run the prompt by hand to see the raw error.');
|
|
253
|
+
}
|
|
254
|
+
let resultObject = null;
|
|
255
|
+
let parsedWhole = false;
|
|
256
|
+
try {
|
|
257
|
+
resultObject = asRecord(JSON.parse(trimmed));
|
|
258
|
+
parsedWhole = resultObject !== null;
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
parsedWhole = false;
|
|
262
|
+
}
|
|
263
|
+
const notices = [];
|
|
264
|
+
if (!parsedWhole) {
|
|
265
|
+
// Tolerate warning lines around the result object; anything that is not
|
|
266
|
+
// JSON becomes a notice so a newer CLI cannot break the log.
|
|
267
|
+
for (const line of trimmed.split('\n')) {
|
|
268
|
+
const candidate = line.trim();
|
|
269
|
+
if (!candidate) {
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
const parsed = asRecord(JSON.parse(candidate));
|
|
274
|
+
if (parsed) {
|
|
275
|
+
resultObject = parsed;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch {
|
|
279
|
+
notices.push({
|
|
280
|
+
kind: 'notice',
|
|
281
|
+
message: `unparseable cursor-agent output: ${candidate.slice(0, 300)}`,
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (!resultObject) {
|
|
287
|
+
throw new Error(`cursor-agent returned unexpected (non-JSON) output: ${trimmed.slice(0, 300)} Re-run the prompt by hand with --output-format json to see the raw error.`);
|
|
288
|
+
}
|
|
289
|
+
// Session aliases are chat-id shaped only: a bare `id` may be a request
|
|
290
|
+
// or message id rather than the chat id, which would resume the wrong
|
|
291
|
+
// session.
|
|
292
|
+
const sessionId = firstString(resultObject, ['session_id', 'sessionId', 'chat_id', 'chatId']) ??
|
|
293
|
+
opts.resumeId ??
|
|
294
|
+
null;
|
|
295
|
+
const withSession = sessionId ? { sessionId } : {};
|
|
296
|
+
const errorValue = resultObject.error;
|
|
297
|
+
const errorText = nonEmptyString(errorValue);
|
|
298
|
+
const isErrorFlag = resultObject.is_error === true;
|
|
299
|
+
const subtypeRaw = nonEmptyString(resultObject.subtype);
|
|
300
|
+
const nonSuccessSubtype = subtypeRaw && subtypeRaw !== 'success' ? subtypeRaw : null;
|
|
301
|
+
if (errorText || asRecord(errorValue) || isErrorFlag || nonSuccessSubtype) {
|
|
302
|
+
return [
|
|
303
|
+
...notices.map((notice) => sessionId ? { ...notice, sessionId } : notice),
|
|
304
|
+
{
|
|
305
|
+
kind: 'result',
|
|
306
|
+
subtype: nonSuccessSubtype ?? 'failed',
|
|
307
|
+
result: errorValue ?? resultObject,
|
|
308
|
+
...withSession,
|
|
309
|
+
},
|
|
310
|
+
];
|
|
311
|
+
}
|
|
312
|
+
const events = [...notices];
|
|
313
|
+
const warnings = [
|
|
314
|
+
...stringArray(resultObject.warnings),
|
|
315
|
+
...stringArray(resultObject.notices),
|
|
316
|
+
...stringArray(resultObject.messages).filter((message) => /warn/i.test(message)),
|
|
317
|
+
];
|
|
318
|
+
for (const warning of warnings) {
|
|
319
|
+
events.push({ kind: 'notice', message: warning.slice(0, 500), ...withSession });
|
|
320
|
+
}
|
|
321
|
+
const answerText = firstString(resultObject, [
|
|
322
|
+
'result',
|
|
323
|
+
'text',
|
|
324
|
+
'message',
|
|
325
|
+
'response',
|
|
326
|
+
'output',
|
|
327
|
+
'answer',
|
|
328
|
+
]);
|
|
329
|
+
// Array content blocks (claude-style text/tool_use) when the result nests them.
|
|
330
|
+
const blocks = Array.isArray(resultObject.content) ? resultObject.content : [];
|
|
331
|
+
for (const block of blocks) {
|
|
332
|
+
const record = asRecord(block);
|
|
333
|
+
if (!record) {
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
if ((record.type === 'text' || record.type === undefined) && typeof record.text === 'string' && record.text) {
|
|
337
|
+
events.push({ kind: 'text', text: record.text, ...withSession });
|
|
338
|
+
}
|
|
339
|
+
else if ((record.type === 'tool_use' || record.type === 'function_call') &&
|
|
340
|
+
typeof record.name === 'string' &&
|
|
341
|
+
record.name) {
|
|
342
|
+
events.push({ kind: 'tool', name: record.name, ...withSession });
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
if (answerText) {
|
|
346
|
+
events.push({ kind: 'text', text: answerText, ...withSession });
|
|
347
|
+
}
|
|
348
|
+
const tools = [
|
|
349
|
+
...toolNames(resultObject.tool_calls),
|
|
350
|
+
...toolNames(resultObject.tools_used),
|
|
351
|
+
...toolNames(resultObject.tools),
|
|
352
|
+
];
|
|
353
|
+
for (const name of tools) {
|
|
354
|
+
events.push({ kind: 'tool', name: name.slice(0, 200), ...withSession });
|
|
355
|
+
}
|
|
356
|
+
// A bare session id (including the resume-id fallback) is not content:
|
|
357
|
+
// `{"session_id":"x","result":""}` and `{}` on --resume are empty results.
|
|
358
|
+
const hasContent = answerText !== null ||
|
|
359
|
+
tools.length > 0 ||
|
|
360
|
+
events.some((event) => event.kind === 'text' || event.kind === 'tool');
|
|
361
|
+
if (!hasContent) {
|
|
362
|
+
throw new Error('cursor-agent returned an empty result (exit 0): the result object has no answer text or tool calls — retry the run; if it persists, re-run the prompt by hand to see the raw error.');
|
|
363
|
+
}
|
|
364
|
+
// Mandatory deck receipt on start: without a `◆ ... ·` display_summary
|
|
365
|
+
// line the run cannot prove it bound to the requested deck (Cursor's
|
|
366
|
+
// global MCP entry is last-workspace-wins). Resume is exempt — the
|
|
367
|
+
// harness prints the receipt on the first turn only, so a resumed turn
|
|
368
|
+
// legitimately carries no new receipt. A present-but-wrong receipt is
|
|
369
|
+
// caught by the shared mismatch check in run.ts.
|
|
370
|
+
if (opts.resumeId === undefined && !/◆\s*[^·\r\n]+?\s*·/.test(stdout)) {
|
|
371
|
+
throw new Error("cursor-agent run produced no deck receipt (missing ◆ display_summary line): the session may be bound to another folder's deck. Ask the agent to call get_session_context and print display_summary verbatim, then retry.");
|
|
372
|
+
}
|
|
373
|
+
events.push({ kind: 'result', subtype: 'success', result: resultObject, ...withSession });
|
|
374
|
+
return sessionId
|
|
375
|
+
? events.map((event) => ('sessionId' in event && event.sessionId ? event : { ...event, sessionId }))
|
|
376
|
+
: events;
|
|
377
|
+
}
|
|
378
|
+
function createCursorAdapter(deps = {}) {
|
|
379
|
+
const bin = deps.bin ?? resolveCursorBin();
|
|
380
|
+
const probe = deps.probe ?? defaultCursorProbe;
|
|
381
|
+
const spawnFn = deps.spawn ?? defaultCursorSpawn;
|
|
382
|
+
return {
|
|
383
|
+
id: 'cursor',
|
|
384
|
+
async preflight() {
|
|
385
|
+
const version = probe(bin, ['--version']);
|
|
386
|
+
if (version.code !== 0) {
|
|
387
|
+
return {
|
|
388
|
+
ok: false,
|
|
389
|
+
remedy: `cursor-agent CLI not found (tried "${bin}"): install cursor-agent 2026.10+ and ensure 'cursor-agent' is on PATH (or set CURSOR_BIN=/path/to/cursor-agent), then retry.`,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
const status = probe(bin, ['status', '--format', 'json']);
|
|
393
|
+
if (status.code !== 0 || !isCursorStatusAuthenticated(status.stdout)) {
|
|
394
|
+
return {
|
|
395
|
+
ok: false,
|
|
396
|
+
remedy: 'cursor-agent is not signed in: run `cursor-agent login`, then retry.',
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
return { ok: true };
|
|
400
|
+
},
|
|
401
|
+
planStart(args) {
|
|
402
|
+
if (args.resumeId !== undefined && args.resumeId.startsWith('-')) {
|
|
403
|
+
return {
|
|
404
|
+
ok: false,
|
|
405
|
+
remedy: `Invalid --resume id ${JSON.stringify(args.resumeId)}: session ids never start with '-'. ` +
|
|
406
|
+
'Pass the chat id printed as sessionId in a previous run log.',
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
// --trust is passed on every launch, so every cursor run records the
|
|
410
|
+
// workspace-trust grant.
|
|
411
|
+
return { ok: true, trustOverride: true };
|
|
412
|
+
},
|
|
413
|
+
async *start(args) {
|
|
414
|
+
const argv = buildCursorArgv({
|
|
415
|
+
prompt: args.prompt,
|
|
416
|
+
tools: args.tools,
|
|
417
|
+
...(args.resumeId !== undefined ? { resumeId: args.resumeId } : {}),
|
|
418
|
+
});
|
|
419
|
+
const wrapSpawnError = (error) => new Error(`cursor-agent run failed: ${String(error instanceof Error ? error.message : error).slice(0, 300)}`);
|
|
420
|
+
let child;
|
|
421
|
+
try {
|
|
422
|
+
child = spawnFn(bin, argv, { cwd: args.cwd });
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
throw wrapSpawnError(error);
|
|
426
|
+
}
|
|
427
|
+
const lines = [];
|
|
428
|
+
try {
|
|
429
|
+
for await (const line of child.stdout) {
|
|
430
|
+
lines.push(line);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
throw wrapSpawnError(error);
|
|
435
|
+
}
|
|
436
|
+
let settled;
|
|
437
|
+
try {
|
|
438
|
+
settled = await child.wait();
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
throw wrapSpawnError(error);
|
|
442
|
+
}
|
|
443
|
+
const { code, stderrTail } = settled;
|
|
444
|
+
if (code !== 0) {
|
|
445
|
+
throw new Error(`cursor-agent exited with code ${code}${stderrTail ? `: ${stderrTail.slice(0, 300)}` : ''}`);
|
|
446
|
+
}
|
|
447
|
+
// Single-shot json: the whole stdout is one result object, so every
|
|
448
|
+
// event lands here, when the process exits.
|
|
449
|
+
yield* cursorEventsFromOutput(lines.join('\n'), {
|
|
450
|
+
...(args.resumeId !== undefined ? { resumeId: args.resumeId } : {}),
|
|
451
|
+
});
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
}
|
|
455
|
+
//# sourceMappingURL=run-cursor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-cursor.js","sourceRoot":"","sources":["../src/run-cursor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agent-deck run --detach` — start the same run in a new session (NOT-401).
|
|
3
|
+
*
|
|
4
|
+
* The starter validates the launch exactly like a foreground run, allocates the
|
|
5
|
+
* run id and log path, then re-executes the CLI as a detached child (`detached:
|
|
6
|
+
* true` calls setsid on POSIX, so the child survives the calling shell, SSH
|
|
7
|
+
* session, or tool call going away) with stdin from /dev/null and stdout/stderr
|
|
8
|
+
* to `run.out` next to the log. Every flag of the starter is passed through
|
|
9
|
+
* unchanged, so a `--tools edit` run cannot silently run as readonly.
|
|
10
|
+
*
|
|
11
|
+
* The starter prints `runId`, child `pid`, and the log path, then exits 0
|
|
12
|
+
* within DETACH_FIRST_LINE_TIMEOUT_MS. Only one outcome is a starter failure:
|
|
13
|
+
* the child died before writing its first log line — that surfaces as exit 1
|
|
14
|
+
* with the tail of the child's captured output.
|
|
15
|
+
*/
|
|
16
|
+
import { type ChildProcess, type SpawnOptions } from 'node:child_process';
|
|
17
|
+
import { type RunDeps, type RunOptions } from './run';
|
|
18
|
+
/** Bounded starter return: never wait longer than this for the first log line. */
|
|
19
|
+
export declare const DETACH_FIRST_LINE_TIMEOUT_MS = 5000;
|
|
20
|
+
/** Child stdout/stderr sink, always next to the JSONL log. */
|
|
21
|
+
export declare function resolveRunOutPath(logPath: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Child argv for the re-exec: the starter's own tokens verbatim (so a `--prompt`
|
|
24
|
+
* value that happens to read `--detach` still arrives intact), minus `--detach`
|
|
25
|
+
* itself, plus an explicit `--log` when the starter relied on the default and
|
|
26
|
+
* the allocated `--_run-id` so the child reuses the same run record.
|
|
27
|
+
*/
|
|
28
|
+
export declare function buildDetachedChildArgs(originalArgs: string[], runId: string, logPath: string): string[];
|
|
29
|
+
export type DetachedStarterDeps = RunDeps & {
|
|
30
|
+
/** Override for unit tests; production spawns the real CLI entry. */
|
|
31
|
+
spawnFn?: (command: string, args: string[], options: SpawnOptions) => ChildProcess;
|
|
32
|
+
cliEntry?: string;
|
|
33
|
+
firstLineTimeoutMs?: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function startDetachedRun(originalArgs: string[], options: RunOptions, deps?: DetachedStarterDeps): Promise<number>;
|
|
36
|
+
//# sourceMappingURL=run-detach.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run-detach.d.ts","sourceRoot":"","sources":["../src/run-detach.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMjF,OAAO,EAIL,KAAK,OAAO,EAEZ,KAAK,UAAU,EAChB,MAAM,OAAO,CAAC;AAEf,kFAAkF;AAClF,eAAO,MAAM,4BAA4B,OAAO,CAAC;AAQjD,8DAA8D;AAC9D,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAcD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,MAAM,EAAE,EACtB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,MAAM,EAAE,CA6BV;AAED,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG;IAC1C,qEAAqE;IACrE,OAAO,CAAC,EAAE,CACR,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,YAAY,KAClB,YAAY,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AA8BF,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,EAAE,UAAU,EACnB,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAgIjB"}
|