@sideboard-ai/core 0.1.111 → 0.1.116
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/agents/cursor-runner.cjs +51 -21
- package/dist/agents/cursor-runner.js +3 -3
- package/dist/{agents-NN22A4G5.js → agents-7NIX44RB.js} +7 -7
- package/dist/{agents-GH3FWDW2.js → agents-DU7DHY7A.js} +10 -10
- package/dist/{chunk-JTQQPJAU.js → chunk-4HOFVKPC.js} +52 -38
- package/dist/{chunk-4EWPKYOU.js → chunk-4OJMZ6P2.js} +2 -2
- package/dist/{chunk-NC3U42ZP.js → chunk-5KSLD4MU.js} +317 -33
- package/dist/{chunk-KQBI5HNT.js → chunk-7WC5UWEB.js} +2 -2
- package/dist/{chunk-WIHKHR5R.js → chunk-AXQ4ZWHK.js} +5 -0
- package/dist/{chunk-LGXBYZZA.js → chunk-DVM4ID64.js} +69 -13
- package/dist/{chunk-DMJKOFTO.js → chunk-DWP25N32.js} +44 -35
- package/dist/{chunk-2GO3YKBA.js → chunk-EKIDHL2T.js} +4 -4
- package/dist/{chunk-C4KHDW3U.js → chunk-FZCIQYNQ.js} +1 -1
- package/dist/{chunk-363Z34PY.js → chunk-GBY7OOMB.js} +273 -218
- package/dist/{chunk-7KWYXGIU.js → chunk-K3TIQXOH.js} +2 -2
- package/dist/{chunk-3KETJKYA.js → chunk-KPIYENTF.js} +69 -13
- package/dist/{chunk-KVFNTWFG.js → chunk-OFF5AFCR.js} +300 -43
- package/dist/{chunk-VOD3HFLP.js → chunk-XOYQ7LNQ.js} +2 -2
- package/dist/{chunk-7YKXHBIW.js → chunk-YMRT2DU6.js} +3 -3
- package/dist/{chunk-YXDR43ZC.js → chunk-ZMROW673.js} +5 -5
- package/dist/{chunk-YFAXVUY2.js → chunk-ZRCX43LS.js} +2 -2
- package/dist/{chunk-AROMOP3C.js → chunk-ZYEFCSZJ.js} +2 -2
- package/dist/{connected-teams-M5XNXRI5.js → connected-teams-O6D4PM7A.js} +2 -2
- package/dist/{connected-teams-J4I5AKMR.js → connected-teams-ZCOU6KCD.js} +2 -2
- package/dist/{coordinator-prompt-AR66L3N4.js → coordinator-prompt-4KCALEKD.js} +3 -3
- package/dist/{coordinator-prompt-BHMLWL64.js → coordinator-prompt-FML4I5AR.js} +3 -3
- package/dist/{global-workspace-XSUFEIAQ.js → global-workspace-CSWABOG5.js} +4 -4
- package/dist/{global-workspace-SKFODUQQ.js → global-workspace-H4YNASM6.js} +4 -4
- package/dist/index.cjs +855 -440
- package/dist/index.d.cts +59 -1
- package/dist/index.d.ts +59 -1
- package/dist/index.js +37 -17
- package/dist/mcp/run-stdio.cjs +966 -635
- package/dist/mcp/run-stdio.js +20 -16
- package/dist/{orchestrator-4T2SXDZ7.js → orchestrator-NXPANCZA.js} +8 -8
- package/dist/{orchestrator-EP57AB5W.js → orchestrator-ZY4RUJKT.js} +10 -10
- package/dist/{run-XKTAJRWF.js → run-USF6FRKV.js} +3 -1
- package/dist/{run-CFKZPY7F.js → run-XQKGHQZ2.js} +3 -1
- package/dist/{workspaces-XAQVKTLO.js → workspaces-HJ3EVATC.js} +5 -5
- package/dist/{workspaces-HV3J4TTW.js → workspaces-QG6PGFQR.js} +5 -5
- package/dist/{worktree-XFJED3VU.js → worktree-IW3BX26B.js} +2 -2
- package/dist/{worktree-N2EV24EE.js → worktree-OTFQO2W7.js} +2 -2
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-4TR3HZFT.js";
|
|
5
5
|
import {
|
|
6
6
|
run
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-DVM4ID64.js";
|
|
8
8
|
|
|
9
9
|
// src/agents/error-detail.ts
|
|
10
10
|
function formatUnknownDetail(err) {
|
|
@@ -90,7 +90,7 @@ function looksLikeHomebrewLibuvCrash(text) {
|
|
|
90
90
|
var NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
|
|
91
91
|
var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
|
|
92
92
|
var BUNDLED_NODE_CRASH_SUMMARY = "Cursor runner crashed in Node. Retry the turn.";
|
|
93
|
-
var V8_OOM_SUMMARY = "
|
|
93
|
+
var V8_OOM_SUMMARY = "Agent ran out of memory (JavaScript heap). If it keeps happening, exclude large files from the project folder.";
|
|
94
94
|
var MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
|
|
95
95
|
function clipStderr(text, maxChars) {
|
|
96
96
|
const trimmed = text.trim();
|
|
@@ -145,6 +145,7 @@ function looksLikeRetryableRunnerCrash(text) {
|
|
|
145
145
|
}
|
|
146
146
|
function shouldRetryFailedAgentTurn(detail, opts) {
|
|
147
147
|
if (looksLikeInvalidAgentSession(detail) && opts.hasSession) return true;
|
|
148
|
+
if (looksLikeV8Oom(detail) && opts.hasSession) return true;
|
|
148
149
|
return looksLikeRetryableRunnerCrash(detail);
|
|
149
150
|
}
|
|
150
151
|
function looksLikeAgentFailureMessage(text) {
|
|
@@ -230,219 +231,6 @@ function formatTurnExitError(exitCode, stderrSummary) {
|
|
|
230
231
|
return `exit ${code}: ${detail}`;
|
|
231
232
|
}
|
|
232
233
|
|
|
233
|
-
// src/agents/cursor-events.ts
|
|
234
|
-
function usageFromCursor(usage) {
|
|
235
|
-
if (!usage) return null;
|
|
236
|
-
const inputTokens = Number(usage.inputTokens ?? 0);
|
|
237
|
-
const outputTokens = Number(usage.outputTokens ?? 0);
|
|
238
|
-
if (!inputTokens && !outputTokens) return null;
|
|
239
|
-
return {
|
|
240
|
-
inputTokens,
|
|
241
|
-
outputTokens,
|
|
242
|
-
cacheReadTokens: usage.cacheReadTokens ? Number(usage.cacheReadTokens) : void 0,
|
|
243
|
-
cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
|
|
244
|
-
};
|
|
245
|
-
}
|
|
246
|
-
function asRecord(value) {
|
|
247
|
-
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
248
|
-
return value;
|
|
249
|
-
}
|
|
250
|
-
return void 0;
|
|
251
|
-
}
|
|
252
|
-
function normalizeCursorToolCall(name, args) {
|
|
253
|
-
const raw = asRecord(args);
|
|
254
|
-
const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
|
|
255
|
-
const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord(raw?.args) != null);
|
|
256
|
-
if (looksLikeMcp && toolName) {
|
|
257
|
-
const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
|
|
258
|
-
const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
259
|
-
const nested = asRecord(raw.args);
|
|
260
|
-
return {
|
|
261
|
-
name: `mcp__${provider}__${toolName}`,
|
|
262
|
-
input: nested ?? { toolName }
|
|
263
|
-
};
|
|
264
|
-
}
|
|
265
|
-
return { name, input: raw };
|
|
266
|
-
}
|
|
267
|
-
function unwrapCursorToolResult(result) {
|
|
268
|
-
if (result == null) return void 0;
|
|
269
|
-
if (typeof result === "string") return result;
|
|
270
|
-
const rec = asRecord(result);
|
|
271
|
-
if (!rec) {
|
|
272
|
-
try {
|
|
273
|
-
return JSON.stringify(result);
|
|
274
|
-
} catch {
|
|
275
|
-
return String(result);
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
const collectTexts = (items) => {
|
|
279
|
-
const texts = [];
|
|
280
|
-
for (const item of items) {
|
|
281
|
-
const row = asRecord(item);
|
|
282
|
-
if (!row) continue;
|
|
283
|
-
if (typeof row.text === "string") {
|
|
284
|
-
texts.push(row.text);
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
const nested = asRecord(row.text);
|
|
288
|
-
if (typeof nested?.text === "string") texts.push(nested.text);
|
|
289
|
-
}
|
|
290
|
-
return texts;
|
|
291
|
-
};
|
|
292
|
-
const value = asRecord(rec.value);
|
|
293
|
-
if (value && Array.isArray(value.content)) {
|
|
294
|
-
const texts = collectTexts(value.content);
|
|
295
|
-
if (texts.length) return texts.join("\n");
|
|
296
|
-
}
|
|
297
|
-
if (Array.isArray(rec.content)) {
|
|
298
|
-
const texts = collectTexts(rec.content);
|
|
299
|
-
if (texts.length) return texts.join("\n");
|
|
300
|
-
}
|
|
301
|
-
try {
|
|
302
|
-
return JSON.stringify(result);
|
|
303
|
-
} catch {
|
|
304
|
-
return String(result);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
function cursorToolResultIsError(status, result) {
|
|
308
|
-
if (status === "error") return true;
|
|
309
|
-
const rec = asRecord(result);
|
|
310
|
-
if (!rec) return false;
|
|
311
|
-
if (rec.status === "error") return true;
|
|
312
|
-
const value = asRecord(rec.value);
|
|
313
|
-
return value?.isError === true;
|
|
314
|
-
}
|
|
315
|
-
function cursorSdkMessageToEvents(msg) {
|
|
316
|
-
if (!msg?.type) return [];
|
|
317
|
-
if (msg.type === "system" && msg.agent_id) {
|
|
318
|
-
return [{ type: "session_id", data: msg.agent_id }];
|
|
319
|
-
}
|
|
320
|
-
if (msg.type === "thinking" && msg.text) {
|
|
321
|
-
return [{ type: "thinking", data: msg.text }];
|
|
322
|
-
}
|
|
323
|
-
if (msg.type === "assistant" && msg.message?.content?.length) {
|
|
324
|
-
const out = [];
|
|
325
|
-
for (const block of msg.message.content) {
|
|
326
|
-
if (block?.type === "text" && block.text) {
|
|
327
|
-
out.push({ type: "stdout", data: block.text });
|
|
328
|
-
} else if (block?.type === "tool_use" && block.id && block.name) {
|
|
329
|
-
const normalized = normalizeCursorToolCall(block.name, block.input);
|
|
330
|
-
out.push({
|
|
331
|
-
type: "tool_use",
|
|
332
|
-
id: block.id,
|
|
333
|
-
name: normalized.name,
|
|
334
|
-
input: normalized.input
|
|
335
|
-
});
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
return out;
|
|
339
|
-
}
|
|
340
|
-
if (msg.type === "tool_call" && msg.call_id && msg.name) {
|
|
341
|
-
const normalized = normalizeCursorToolCall(msg.name, msg.args);
|
|
342
|
-
if (msg.status === "running") {
|
|
343
|
-
return [
|
|
344
|
-
{
|
|
345
|
-
type: "tool_use",
|
|
346
|
-
id: msg.call_id,
|
|
347
|
-
name: normalized.name,
|
|
348
|
-
input: normalized.input
|
|
349
|
-
}
|
|
350
|
-
];
|
|
351
|
-
}
|
|
352
|
-
if (msg.status === "completed" || msg.status === "error") {
|
|
353
|
-
return [
|
|
354
|
-
{
|
|
355
|
-
type: "tool_use",
|
|
356
|
-
id: msg.call_id,
|
|
357
|
-
name: normalized.name,
|
|
358
|
-
input: normalized.input
|
|
359
|
-
},
|
|
360
|
-
{
|
|
361
|
-
type: "tool_result",
|
|
362
|
-
id: msg.call_id,
|
|
363
|
-
content: unwrapCursorToolResult(msg.result),
|
|
364
|
-
isError: cursorToolResultIsError(msg.status, msg.result)
|
|
365
|
-
}
|
|
366
|
-
];
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (msg.type === "usage") {
|
|
370
|
-
const usage = usageFromCursor(msg.usage);
|
|
371
|
-
if (usage) return [{ type: "usage", data: usage, scope: "request" }];
|
|
372
|
-
}
|
|
373
|
-
if (msg.type === "status" && msg.status === "ERROR") {
|
|
374
|
-
const rawMessage = msg.message;
|
|
375
|
-
const detail = (typeof rawMessage === "string" ? rawMessage.trim() : "") || extractJsonErrorMessage(msg) || formatUnknownDetail(msg.error) || msg.text || "Cursor run entered ERROR status";
|
|
376
|
-
return [{ type: "stderr", data: detail }];
|
|
377
|
-
}
|
|
378
|
-
if (msg.type === "error") {
|
|
379
|
-
const detail = extractJsonErrorMessage(msg) || formatUnknownDetail(msg.error) || msg.text || "Cursor run error";
|
|
380
|
-
return [{ type: "stderr", data: detail }];
|
|
381
|
-
}
|
|
382
|
-
return [];
|
|
383
|
-
}
|
|
384
|
-
function nestedUpdateToEvents(update, parentId) {
|
|
385
|
-
if (update.type === "thinking-delta" && update.text) {
|
|
386
|
-
return [{ type: "thinking", data: update.text, parentId }];
|
|
387
|
-
}
|
|
388
|
-
if (update.type === "text-delta" && update.text) {
|
|
389
|
-
return [{ type: "stdout", data: update.text, parentId }];
|
|
390
|
-
}
|
|
391
|
-
if ((update.type === "tool-call-started" || update.type === "tool-call-completed") && update.callId && update.toolCall) {
|
|
392
|
-
const rawName = typeof update.toolCall.type === "string" ? update.toolCall.type : "tool";
|
|
393
|
-
const normalized = normalizeCursorToolCall(rawName, update.toolCall.args);
|
|
394
|
-
const events = [
|
|
395
|
-
{
|
|
396
|
-
type: "tool_use",
|
|
397
|
-
id: update.callId,
|
|
398
|
-
name: normalized.name,
|
|
399
|
-
input: normalized.input,
|
|
400
|
-
parentId
|
|
401
|
-
}
|
|
402
|
-
];
|
|
403
|
-
if (update.type === "tool-call-completed") {
|
|
404
|
-
events.push({
|
|
405
|
-
type: "tool_result",
|
|
406
|
-
id: update.callId,
|
|
407
|
-
content: unwrapCursorToolResult(update.toolCall.result),
|
|
408
|
-
isError: cursorToolResultIsError(void 0, update.toolCall.result),
|
|
409
|
-
parentId
|
|
410
|
-
});
|
|
411
|
-
}
|
|
412
|
-
return events;
|
|
413
|
-
}
|
|
414
|
-
return [];
|
|
415
|
-
}
|
|
416
|
-
function cursorDeltaToEvents(update) {
|
|
417
|
-
if (!update?.type) return [];
|
|
418
|
-
if (update.type === "tool-call-delta" && update.callId && update.taskUpdate) {
|
|
419
|
-
return nestedUpdateToEvents(update.taskUpdate, update.callId);
|
|
420
|
-
}
|
|
421
|
-
return [];
|
|
422
|
-
}
|
|
423
|
-
function parseCursorRunnerLine(line) {
|
|
424
|
-
const trimmed = line.trim();
|
|
425
|
-
if (!trimmed) return null;
|
|
426
|
-
try {
|
|
427
|
-
const obj = JSON.parse(trimmed);
|
|
428
|
-
if (Array.isArray(obj)) return obj;
|
|
429
|
-
if (obj && typeof obj === "object" && "events" in obj && Array.isArray(obj.events)) {
|
|
430
|
-
return obj.events;
|
|
431
|
-
}
|
|
432
|
-
if (obj && typeof obj === "object" && "type" in obj) {
|
|
433
|
-
return obj;
|
|
434
|
-
}
|
|
435
|
-
return null;
|
|
436
|
-
} catch {
|
|
437
|
-
return { type: "stdout", data: line };
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
// src/agents/cursor-ripgrep.ts
|
|
442
|
-
import { existsSync as existsSync3 } from "fs";
|
|
443
|
-
import { createRequire } from "module";
|
|
444
|
-
import { dirname, isAbsolute, join as join3, parse, resolve as resolvePath } from "path";
|
|
445
|
-
|
|
446
234
|
// src/agents/node-launch.ts
|
|
447
235
|
import { existsSync as existsSync2, readdirSync, realpathSync } from "fs";
|
|
448
236
|
import { homedir } from "os";
|
|
@@ -492,6 +280,29 @@ function packagedCursorRipgrepCandidate(platformPkg, binName) {
|
|
|
492
280
|
}
|
|
493
281
|
|
|
494
282
|
// src/agents/node-launch.ts
|
|
283
|
+
var AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
|
|
284
|
+
var MAX_OLD_SPACE_FLAG = /(?:^|\s)(--max[-_]old[-_]space[-_]size)(?:[= ](\d+))?(?=\s|$)/;
|
|
285
|
+
function withMaxOldSpaceSize(nodeOptions, heapMb) {
|
|
286
|
+
const existing = (nodeOptions ?? "").trim();
|
|
287
|
+
const match = MAX_OLD_SPACE_FLAG.exec(existing);
|
|
288
|
+
if (match) {
|
|
289
|
+
const current = match[2] ? Number(match[2]) : 0;
|
|
290
|
+
if (Number.isFinite(current) && current >= heapMb) return existing;
|
|
291
|
+
return existing.replace(MAX_OLD_SPACE_FLAG, ` --max-old-space-size=${heapMb}`).trim();
|
|
292
|
+
}
|
|
293
|
+
return existing ? `${existing} --max-old-space-size=${heapMb}` : `--max-old-space-size=${heapMb}`;
|
|
294
|
+
}
|
|
295
|
+
function applyAgentRunnerHeapEnv(env) {
|
|
296
|
+
env.NODE_OPTIONS = withMaxOldSpaceSize(
|
|
297
|
+
env.NODE_OPTIONS,
|
|
298
|
+
AGENT_RUNNER_MAX_OLD_SPACE_MB
|
|
299
|
+
);
|
|
300
|
+
}
|
|
301
|
+
function envWithAgentHeap(env) {
|
|
302
|
+
const next = { ...env };
|
|
303
|
+
applyAgentRunnerHeapEnv(next);
|
|
304
|
+
return next;
|
|
305
|
+
}
|
|
495
306
|
function isAsarPath(filePath) {
|
|
496
307
|
if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
|
|
497
308
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
@@ -628,13 +439,21 @@ async function findSystemNode() {
|
|
|
628
439
|
function applyNodeLaunch(launch, args) {
|
|
629
440
|
const readableArgs = args.map(nodeReadableScriptPath);
|
|
630
441
|
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
631
|
-
return {
|
|
442
|
+
return {
|
|
443
|
+
file: launch.file,
|
|
444
|
+
args: readableArgs,
|
|
445
|
+
env: envWithAgentHeap(launch.env)
|
|
446
|
+
};
|
|
632
447
|
}
|
|
633
448
|
const wrapped = wrapElectronAsNodeLaunch(launch.file, readableArgs);
|
|
634
449
|
if (process.platform === "win32") {
|
|
635
|
-
return {
|
|
450
|
+
return {
|
|
451
|
+
file: wrapped.file,
|
|
452
|
+
args: wrapped.args,
|
|
453
|
+
env: envWithAgentHeap(launch.env)
|
|
454
|
+
};
|
|
636
455
|
}
|
|
637
|
-
const env =
|
|
456
|
+
const env = envWithAgentHeap(launch.env);
|
|
638
457
|
delete env.ELECTRON_RUN_AS_NODE;
|
|
639
458
|
return { file: wrapped.file, args: wrapped.args, env };
|
|
640
459
|
}
|
|
@@ -656,7 +475,239 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
656
475
|
};
|
|
657
476
|
}
|
|
658
477
|
|
|
478
|
+
// src/agents/cursor-events.ts
|
|
479
|
+
function usageFromCursor(usage) {
|
|
480
|
+
if (!usage) return null;
|
|
481
|
+
const inputTokens = Number(usage.inputTokens ?? 0);
|
|
482
|
+
const outputTokens = Number(usage.outputTokens ?? 0);
|
|
483
|
+
if (!inputTokens && !outputTokens) return null;
|
|
484
|
+
return {
|
|
485
|
+
inputTokens,
|
|
486
|
+
outputTokens,
|
|
487
|
+
cacheReadTokens: usage.cacheReadTokens ? Number(usage.cacheReadTokens) : void 0,
|
|
488
|
+
cacheWriteTokens: usage.cacheWriteTokens ? Number(usage.cacheWriteTokens) : void 0
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
function asRecord(value) {
|
|
492
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
493
|
+
return value;
|
|
494
|
+
}
|
|
495
|
+
return void 0;
|
|
496
|
+
}
|
|
497
|
+
function normalizeCursorToolCall(name, args) {
|
|
498
|
+
const raw = asRecord(args);
|
|
499
|
+
const toolName = typeof raw?.toolName === "string" && raw.toolName.trim() ? raw.toolName.trim() : null;
|
|
500
|
+
const looksLikeMcp = name === "mcp" || toolName != null && (typeof raw?.providerIdentifier === "string" || asRecord(raw?.args) != null);
|
|
501
|
+
if (looksLikeMcp && toolName) {
|
|
502
|
+
const providerRaw = typeof raw.providerIdentifier === "string" && raw.providerIdentifier.trim() ? raw.providerIdentifier.trim() : "sideboard";
|
|
503
|
+
const provider = providerRaw.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
504
|
+
const nested = asRecord(raw.args);
|
|
505
|
+
return {
|
|
506
|
+
name: `mcp__${provider}__${toolName}`,
|
|
507
|
+
input: nested ?? { toolName }
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
return { name, input: raw };
|
|
511
|
+
}
|
|
512
|
+
function unwrapCursorToolResult(result) {
|
|
513
|
+
if (result == null) return void 0;
|
|
514
|
+
if (typeof result === "string") return result;
|
|
515
|
+
const rec = asRecord(result);
|
|
516
|
+
if (!rec) {
|
|
517
|
+
try {
|
|
518
|
+
return JSON.stringify(result);
|
|
519
|
+
} catch {
|
|
520
|
+
return String(result);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
const collectTexts = (items) => {
|
|
524
|
+
const texts = [];
|
|
525
|
+
for (const item of items) {
|
|
526
|
+
const row = asRecord(item);
|
|
527
|
+
if (!row) continue;
|
|
528
|
+
if (typeof row.text === "string") {
|
|
529
|
+
texts.push(row.text);
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
const nested = asRecord(row.text);
|
|
533
|
+
if (typeof nested?.text === "string") texts.push(nested.text);
|
|
534
|
+
}
|
|
535
|
+
return texts;
|
|
536
|
+
};
|
|
537
|
+
const value = asRecord(rec.value);
|
|
538
|
+
if (value && Array.isArray(value.content)) {
|
|
539
|
+
const texts = collectTexts(value.content);
|
|
540
|
+
if (texts.length) return texts.join("\n");
|
|
541
|
+
}
|
|
542
|
+
if (Array.isArray(rec.content)) {
|
|
543
|
+
const texts = collectTexts(rec.content);
|
|
544
|
+
if (texts.length) return texts.join("\n");
|
|
545
|
+
}
|
|
546
|
+
try {
|
|
547
|
+
return JSON.stringify(result);
|
|
548
|
+
} catch {
|
|
549
|
+
return String(result);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
function cursorToolResultIsError(status, result) {
|
|
553
|
+
if (status === "error") return true;
|
|
554
|
+
const rec = asRecord(result);
|
|
555
|
+
if (!rec) return false;
|
|
556
|
+
if (rec.status === "error") return true;
|
|
557
|
+
const value = asRecord(rec.value);
|
|
558
|
+
return value?.isError === true;
|
|
559
|
+
}
|
|
560
|
+
function cursorSdkMessageToEvents(msg) {
|
|
561
|
+
if (!msg?.type) return [];
|
|
562
|
+
if (msg.type === "system" && msg.agent_id) {
|
|
563
|
+
return [{ type: "session_id", data: msg.agent_id }];
|
|
564
|
+
}
|
|
565
|
+
if (msg.type === "thinking" && msg.text) {
|
|
566
|
+
return [{ type: "thinking", data: msg.text }];
|
|
567
|
+
}
|
|
568
|
+
if (msg.type === "assistant" && msg.message?.content?.length) {
|
|
569
|
+
const out = [];
|
|
570
|
+
for (const block of msg.message.content) {
|
|
571
|
+
if (block?.type === "text" && block.text) {
|
|
572
|
+
out.push({ type: "stdout", data: block.text });
|
|
573
|
+
} else if (block?.type === "tool_use" && block.id && block.name) {
|
|
574
|
+
const normalized = normalizeCursorToolCall(block.name, block.input);
|
|
575
|
+
out.push({
|
|
576
|
+
type: "tool_use",
|
|
577
|
+
id: block.id,
|
|
578
|
+
name: normalized.name,
|
|
579
|
+
input: normalized.input
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
return out;
|
|
584
|
+
}
|
|
585
|
+
if (msg.type === "tool_call" && msg.call_id && msg.name) {
|
|
586
|
+
const normalized = normalizeCursorToolCall(msg.name, msg.args);
|
|
587
|
+
if (msg.status === "running") {
|
|
588
|
+
const events = [
|
|
589
|
+
{
|
|
590
|
+
type: "tool_use",
|
|
591
|
+
id: msg.call_id,
|
|
592
|
+
name: normalized.name,
|
|
593
|
+
input: normalized.input
|
|
594
|
+
}
|
|
595
|
+
];
|
|
596
|
+
const live = unwrapCursorToolResult(msg.result);
|
|
597
|
+
if (live) {
|
|
598
|
+
events.push({
|
|
599
|
+
type: "tool_result",
|
|
600
|
+
id: msg.call_id,
|
|
601
|
+
content: live,
|
|
602
|
+
partial: true
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
return events;
|
|
606
|
+
}
|
|
607
|
+
if (msg.status === "completed" || msg.status === "error") {
|
|
608
|
+
return [
|
|
609
|
+
{
|
|
610
|
+
type: "tool_use",
|
|
611
|
+
id: msg.call_id,
|
|
612
|
+
name: normalized.name,
|
|
613
|
+
input: normalized.input
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
type: "tool_result",
|
|
617
|
+
id: msg.call_id,
|
|
618
|
+
content: unwrapCursorToolResult(msg.result),
|
|
619
|
+
isError: cursorToolResultIsError(msg.status, msg.result)
|
|
620
|
+
}
|
|
621
|
+
];
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
if (msg.type === "usage") {
|
|
625
|
+
const usage = usageFromCursor(msg.usage);
|
|
626
|
+
if (usage) return [{ type: "usage", data: usage, scope: "request" }];
|
|
627
|
+
}
|
|
628
|
+
if (msg.type === "status" && msg.status === "ERROR") {
|
|
629
|
+
const rawMessage = msg.message;
|
|
630
|
+
const detail = (typeof rawMessage === "string" ? rawMessage.trim() : "") || extractJsonErrorMessage(msg) || formatUnknownDetail(msg.error) || msg.text || "Cursor run entered ERROR status";
|
|
631
|
+
return [{ type: "stderr", data: detail }];
|
|
632
|
+
}
|
|
633
|
+
if (msg.type === "error") {
|
|
634
|
+
const detail = extractJsonErrorMessage(msg) || formatUnknownDetail(msg.error) || msg.text || "Cursor run error";
|
|
635
|
+
return [{ type: "stderr", data: detail }];
|
|
636
|
+
}
|
|
637
|
+
return [];
|
|
638
|
+
}
|
|
639
|
+
function nestedUpdateToEvents(update, parentId) {
|
|
640
|
+
if (update.type === "thinking-delta" && update.text) {
|
|
641
|
+
return [{ type: "thinking", data: update.text, parentId }];
|
|
642
|
+
}
|
|
643
|
+
if (update.type === "text-delta" && update.text) {
|
|
644
|
+
return [{ type: "stdout", data: update.text, parentId }];
|
|
645
|
+
}
|
|
646
|
+
if ((update.type === "tool-call-started" || update.type === "tool-call-completed") && update.callId && update.toolCall) {
|
|
647
|
+
const rawName = typeof update.toolCall.type === "string" ? update.toolCall.type : "tool";
|
|
648
|
+
const normalized = normalizeCursorToolCall(rawName, update.toolCall.args);
|
|
649
|
+
const events = [
|
|
650
|
+
{
|
|
651
|
+
type: "tool_use",
|
|
652
|
+
id: update.callId,
|
|
653
|
+
name: normalized.name,
|
|
654
|
+
input: normalized.input,
|
|
655
|
+
parentId
|
|
656
|
+
}
|
|
657
|
+
];
|
|
658
|
+
if (update.type === "tool-call-completed") {
|
|
659
|
+
events.push({
|
|
660
|
+
type: "tool_result",
|
|
661
|
+
id: update.callId,
|
|
662
|
+
content: unwrapCursorToolResult(update.toolCall.result),
|
|
663
|
+
isError: cursorToolResultIsError(void 0, update.toolCall.result),
|
|
664
|
+
parentId
|
|
665
|
+
});
|
|
666
|
+
} else {
|
|
667
|
+
const live = unwrapCursorToolResult(update.toolCall.result);
|
|
668
|
+
if (live) {
|
|
669
|
+
events.push({
|
|
670
|
+
type: "tool_result",
|
|
671
|
+
id: update.callId,
|
|
672
|
+
content: live,
|
|
673
|
+
partial: true,
|
|
674
|
+
parentId
|
|
675
|
+
});
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
return events;
|
|
679
|
+
}
|
|
680
|
+
return [];
|
|
681
|
+
}
|
|
682
|
+
function cursorDeltaToEvents(update) {
|
|
683
|
+
if (!update?.type) return [];
|
|
684
|
+
if (update.type === "tool-call-delta" && update.callId && update.taskUpdate) {
|
|
685
|
+
return nestedUpdateToEvents(update.taskUpdate, update.callId);
|
|
686
|
+
}
|
|
687
|
+
return [];
|
|
688
|
+
}
|
|
689
|
+
function parseCursorRunnerLine(line) {
|
|
690
|
+
const trimmed = line.trim();
|
|
691
|
+
if (!trimmed) return null;
|
|
692
|
+
try {
|
|
693
|
+
const obj = JSON.parse(trimmed);
|
|
694
|
+
if (Array.isArray(obj)) return obj;
|
|
695
|
+
if (obj && typeof obj === "object" && "events" in obj && Array.isArray(obj.events)) {
|
|
696
|
+
return obj.events;
|
|
697
|
+
}
|
|
698
|
+
if (obj && typeof obj === "object" && "type" in obj) {
|
|
699
|
+
return obj;
|
|
700
|
+
}
|
|
701
|
+
return null;
|
|
702
|
+
} catch {
|
|
703
|
+
return { type: "stdout", data: line };
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
659
707
|
// src/agents/cursor-ripgrep.ts
|
|
708
|
+
import { existsSync as existsSync3 } from "fs";
|
|
709
|
+
import { createRequire } from "module";
|
|
710
|
+
import { dirname, isAbsolute, join as join3, parse, resolve as resolvePath } from "path";
|
|
660
711
|
var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
|
|
661
712
|
function rgBinaryName() {
|
|
662
713
|
return process.platform === "win32" ? "rg.exe" : "rg";
|
|
@@ -723,6 +774,7 @@ export {
|
|
|
723
774
|
formatUnknownDetail,
|
|
724
775
|
extractJsonErrorMessage,
|
|
725
776
|
pushTurnStderr,
|
|
777
|
+
looksLikeV8Oom,
|
|
726
778
|
summarizeTurnStderr,
|
|
727
779
|
looksLikeInvalidAgentSession,
|
|
728
780
|
shouldRetryFailedAgentTurn,
|
|
@@ -732,6 +784,9 @@ export {
|
|
|
732
784
|
formatTurnExitError,
|
|
733
785
|
packagedCursorRunnerPath,
|
|
734
786
|
packagedMcpStdioPath,
|
|
787
|
+
AGENT_RUNNER_MAX_OLD_SPACE_MB,
|
|
788
|
+
withMaxOldSpaceSize,
|
|
789
|
+
applyAgentRunnerHeapEnv,
|
|
735
790
|
isAsarPath,
|
|
736
791
|
applyNodeLaunch,
|
|
737
792
|
resolveNodeLaunch,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4OJMZ6P2.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureGhPreferOrigin,
|
|
6
6
|
resolveRepoRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-FZCIQYNQ.js";
|
|
8
8
|
import {
|
|
9
9
|
appDataDir
|
|
10
10
|
} from "./chunk-QZQEXME2.js";
|
|
@@ -99,6 +99,34 @@ function withExportedPath(command, pathValue) {
|
|
|
99
99
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// src/git/stale-lock.ts
|
|
103
|
+
import { existsSync as existsSync2, statSync, unlinkSync } from "fs";
|
|
104
|
+
import { join as join2 } from "path";
|
|
105
|
+
var STALE_INDEX_LOCK_MS = 2e4;
|
|
106
|
+
function isIndexLockError(text) {
|
|
107
|
+
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text);
|
|
108
|
+
}
|
|
109
|
+
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
110
|
+
const lockPath = join2(gitDir, "index.lock");
|
|
111
|
+
try {
|
|
112
|
+
if (!existsSync2(lockPath)) return null;
|
|
113
|
+
if (now - statSync(lockPath).mtimeMs < maxAgeMs) return null;
|
|
114
|
+
unlinkSync(lockPath);
|
|
115
|
+
return lockPath;
|
|
116
|
+
} catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
|
|
121
|
+
const now = Date.now();
|
|
122
|
+
const removed = [];
|
|
123
|
+
for (const dir of new Set(gitDirs)) {
|
|
124
|
+
const cleared = clearStaleIndexLock(dir, maxAgeMs, now);
|
|
125
|
+
if (cleared) removed.push(cleared);
|
|
126
|
+
}
|
|
127
|
+
return removed;
|
|
128
|
+
}
|
|
129
|
+
|
|
102
130
|
// src/git/run.ts
|
|
103
131
|
async function run(file, args, opts) {
|
|
104
132
|
ensureAgentPath();
|
|
@@ -126,6 +154,21 @@ async function run(file, args, opts) {
|
|
|
126
154
|
throw err;
|
|
127
155
|
}
|
|
128
156
|
}
|
|
157
|
+
async function resolveGitDirsForLockRecovery(cwd, env = {}) {
|
|
158
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
159
|
+
const [gitDir, commonDir] = await Promise.all([
|
|
160
|
+
run("git", ["rev-parse", "--absolute-git-dir"], { cwd, reject: false, env, timeoutMs: 5e3 }),
|
|
161
|
+
run("git", ["rev-parse", "--path-format=absolute", "--git-common-dir"], {
|
|
162
|
+
cwd,
|
|
163
|
+
reject: false,
|
|
164
|
+
env,
|
|
165
|
+
timeoutMs: 5e3
|
|
166
|
+
})
|
|
167
|
+
]);
|
|
168
|
+
if (gitDir.exitCode === 0 && gitDir.stdout.trim()) dirs.add(gitDir.stdout.trim());
|
|
169
|
+
if (commonDir.exitCode === 0 && commonDir.stdout.trim()) dirs.add(commonDir.stdout.trim());
|
|
170
|
+
return [...dirs];
|
|
171
|
+
}
|
|
129
172
|
async function git(args, cwd, opts) {
|
|
130
173
|
const prefix = [];
|
|
131
174
|
if (opts?.config) {
|
|
@@ -134,21 +177,32 @@ async function git(args, cwd, opts) {
|
|
|
134
177
|
prefix.push("-c", `${key}=${value}`);
|
|
135
178
|
}
|
|
136
179
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
reject: opts?.reject,
|
|
140
|
-
timeoutMs: opts?.timeoutMs,
|
|
180
|
+
const gitArgs = ["--no-pager", ...prefix, ...args];
|
|
181
|
+
const env = {
|
|
141
182
|
// Never block forever on a credential/SSH prompt inside MCP / Electron.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
183
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
184
|
+
GIT_ASKPASS: process.env.GIT_ASKPASS || "echo",
|
|
185
|
+
SSH_ASKPASS: process.env.SSH_ASKPASS || "echo",
|
|
186
|
+
GIT_SSH_COMMAND: process.env.GIT_SSH_COMMAND || "ssh -o BatchMode=yes -o ConnectTimeout=15",
|
|
187
|
+
GCM_INTERACTIVE: "never",
|
|
188
|
+
GH_PROMPT_DISABLED: "1",
|
|
189
|
+
...opts?.env
|
|
190
|
+
};
|
|
191
|
+
let result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
|
|
192
|
+
if (result.exitCode !== 0 && isIndexLockError(result.stderr)) {
|
|
193
|
+
const gitDirs = await resolveGitDirsForLockRecovery(cwd, env);
|
|
194
|
+
const cleared = clearStaleIndexLocks(gitDirs);
|
|
195
|
+
if (cleared.length > 0) {
|
|
196
|
+
result = await run("git", gitArgs, { cwd, reject: false, timeoutMs: opts?.timeoutMs, env });
|
|
150
197
|
}
|
|
151
|
-
}
|
|
198
|
+
}
|
|
199
|
+
if ((opts?.reject ?? true) && result.exitCode !== 0) {
|
|
200
|
+
throw new Error(
|
|
201
|
+
`Command failed with exit code ${result.exitCode}: git ${gitArgs.join(" ")}
|
|
202
|
+
${result.stderr}`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
return result;
|
|
152
206
|
}
|
|
153
207
|
async function gh(args, cwd, opts) {
|
|
154
208
|
return run("gh", args, {
|
|
@@ -176,7 +230,9 @@ export {
|
|
|
176
230
|
posixShellSingleQuote,
|
|
177
231
|
resolveCommandBinarySync,
|
|
178
232
|
withExportedPath,
|
|
233
|
+
clearStaleIndexLocks,
|
|
179
234
|
run,
|
|
235
|
+
resolveGitDirsForLockRecovery,
|
|
180
236
|
git,
|
|
181
237
|
gh,
|
|
182
238
|
resolveGhAuthToken
|