@sideboard-ai/core 0.1.38 → 0.1.41

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.
@@ -198,18 +198,35 @@ async function main() {
198
198
  const store = localAgentStore();
199
199
  const local = { cwd: req.cwd, store };
200
200
  try {
201
- const agent = req.agentId ? await import_sdk.Agent.resume(req.agentId, {
202
- apiKey,
203
- model,
204
- mode,
205
- local
206
- }) : await import_sdk.Agent.create({
207
- apiKey,
208
- model,
209
- mode,
210
- local,
211
- name: "Sideboard"
212
- });
201
+ let agent;
202
+ try {
203
+ agent = req.agentId ? await import_sdk.Agent.resume(req.agentId, {
204
+ apiKey,
205
+ model,
206
+ mode,
207
+ local
208
+ }) : await import_sdk.Agent.create({
209
+ apiKey,
210
+ model,
211
+ mode,
212
+ local,
213
+ name: "Sideboard"
214
+ });
215
+ } catch (err) {
216
+ const message = err instanceof Error ? err.message : String(err);
217
+ if (!req.agentId || !/not found/i.test(message)) throw err;
218
+ emit({
219
+ type: "stderr",
220
+ data: `Cursor agent ${req.agentId} not found \u2014 starting a new session`
221
+ });
222
+ agent = await import_sdk.Agent.create({
223
+ apiKey,
224
+ model,
225
+ mode,
226
+ local,
227
+ name: "Sideboard"
228
+ });
229
+ }
213
230
  try {
214
231
  emit({ type: "session_id", data: agent.agentId });
215
232
  const run = await agent.send(req.prompt);
@@ -62,18 +62,35 @@ async function main() {
62
62
  const store = localAgentStore();
63
63
  const local = { cwd: req.cwd, store };
64
64
  try {
65
- const agent = req.agentId ? await Agent.resume(req.agentId, {
66
- apiKey,
67
- model,
68
- mode,
69
- local
70
- }) : await Agent.create({
71
- apiKey,
72
- model,
73
- mode,
74
- local,
75
- name: "Sideboard"
76
- });
65
+ let agent;
66
+ try {
67
+ agent = req.agentId ? await Agent.resume(req.agentId, {
68
+ apiKey,
69
+ model,
70
+ mode,
71
+ local
72
+ }) : await Agent.create({
73
+ apiKey,
74
+ model,
75
+ mode,
76
+ local,
77
+ name: "Sideboard"
78
+ });
79
+ } catch (err) {
80
+ const message = err instanceof Error ? err.message : String(err);
81
+ if (!req.agentId || !/not found/i.test(message)) throw err;
82
+ emit({
83
+ type: "stderr",
84
+ data: `Cursor agent ${req.agentId} not found \u2014 starting a new session`
85
+ });
86
+ agent = await Agent.create({
87
+ apiKey,
88
+ model,
89
+ mode,
90
+ local,
91
+ name: "Sideboard"
92
+ });
93
+ }
77
94
  try {
78
95
  emit({ type: "session_id", data: agent.agentId });
79
96
  const run = await agent.send(req.prompt);
@@ -21,7 +21,7 @@ import {
21
21
  opencodeAdapter,
22
22
  permissionMode,
23
23
  resolveCursorModelId
24
- } from "./chunk-BEXVE7LX.js";
24
+ } from "./chunk-SX2R2PCE.js";
25
25
  import "./chunk-ILQK4P5R.js";
26
26
  import {
27
27
  cursorSdkMessageToEvents,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  isGlobalRepoPath
3
- } from "./chunk-IS3AGU33.js";
3
+ } from "./chunk-6TZSJMXF.js";
4
4
  import {
5
5
  ensureGhPreferOrigin,
6
6
  resolveRepoRoot
7
- } from "./chunk-XBEQI5H4.js";
7
+ } from "./chunk-VA2U5EQH.js";
8
8
  import {
9
9
  appDataDir
10
10
  } from "./chunk-M37RITA6.js";
@@ -26,6 +26,7 @@ function normalizeThread(raw) {
26
26
  planMode: Boolean(raw.planMode),
27
27
  autonomy: raw.autonomy ?? "default",
28
28
  lastError: raw.lastError ?? null,
29
+ agentPid: raw.agentPid ?? null,
29
30
  attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
30
31
  prTitle: raw.prTitle ?? null,
31
32
  userSetTitle: Boolean(raw.userSetTitle),
@@ -61,7 +62,8 @@ function createEmptyThread(partial) {
61
62
  worktreePath: partial.worktreePath,
62
63
  repoPath: partial.repoPath,
63
64
  agent: partial.agent,
64
- lastError: null
65
+ lastError: null,
66
+ agentPid: null
65
67
  };
66
68
  }
67
69
  async function withThreadLock(id, fn) {
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  ensureGlobalCoordinatorCwd
3
- } from "./chunk-PTASB7SJ.js";
3
+ } from "./chunk-UPMGXM4X.js";
4
4
  import {
5
5
  allocateTeamName,
6
6
  takenSlugsFromThread,
7
7
  teamSlugFromName
8
- } from "./chunk-XBEQI5H4.js";
8
+ } from "./chunk-VA2U5EQH.js";
9
9
  import {
10
10
  createEmptyThread,
11
11
  listThreads,
12
12
  updateThread,
13
13
  writeThread
14
- } from "./chunk-HYRHI3QU.js";
14
+ } from "./chunk-5UIKSPDD.js";
15
15
  import {
16
16
  globalAgentCwd
17
17
  } from "./chunk-M37RITA6.js";
@@ -798,7 +798,7 @@ var claudeAdapter = {
798
798
  );
799
799
  }
800
800
  const mode = permissionMode(thread);
801
- const { isOrchestratorThread } = await import("./global-workspace-QSRP25HQ.js");
801
+ const { isOrchestratorThread } = await import("./global-workspace-4GVWSCEX.js");
802
802
  const isOrchestrator = isOrchestratorThread(thread);
803
803
  const injectedServers = await buildInjectedMcpServers({
804
804
  includeSideboard: true,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveGithubRepoSlug
3
- } from "./chunk-XBEQI5H4.js";
3
+ } from "./chunk-VA2U5EQH.js";
4
4
  import {
5
5
  globalAgentCwd,
6
6
  sideboardReposDir
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  listThreads
3
- } from "./chunk-HYRHI3QU.js";
3
+ } from "./chunk-5UIKSPDD.js";
4
4
  import {
5
5
  worktreesRoot
6
6
  } from "./chunk-M37RITA6.js";
@@ -3,7 +3,7 @@ import {
3
3
  ensureWorkspace,
4
4
  removeWorkspace,
5
5
  syncWorkspacesFromThreads
6
- } from "./chunk-FVGRUZHI.js";
6
+ } from "./chunk-44LYDJFB.js";
7
7
  import {
8
8
  GLOBAL_WORKSPACE_ID,
9
9
  createGlobalChat,
@@ -13,19 +13,19 @@ import {
13
13
  isGlobalThread,
14
14
  isOrchestratorThread,
15
15
  orchestratorSessionPoisonedByBuiltins
16
- } from "./chunk-IS3AGU33.js";
16
+ } from "./chunk-6TZSJMXF.js";
17
17
  import {
18
18
  coordinatorSystemPrompt,
19
19
  coordinatorTurnReminder,
20
20
  enrichWorkspacesWithGithub,
21
21
  ensureGlobalCoordinatorCwd
22
- } from "./chunk-PTASB7SJ.js";
22
+ } from "./chunk-UPMGXM4X.js";
23
23
  import {
24
24
  PLAN_MODE_INSTRUCTION,
25
25
  allAdapters,
26
26
  getAdapter,
27
27
  parseBrightsyCliLine
28
- } from "./chunk-BEXVE7LX.js";
28
+ } from "./chunk-SX2R2PCE.js";
29
29
  import {
30
30
  fallbackTurnFailDetail,
31
31
  formatTurnExitError,
@@ -71,7 +71,7 @@ import {
71
71
  takenSlugsFromThread,
72
72
  threadDisplayLabel,
73
73
  worktreeNameFromPath
74
- } from "./chunk-XBEQI5H4.js";
74
+ } from "./chunk-VA2U5EQH.js";
75
75
  import {
76
76
  appendMessage,
77
77
  createEmptyThread,
@@ -83,7 +83,7 @@ import {
83
83
  updateThread,
84
84
  withThreadLock,
85
85
  writeThread
86
- } from "./chunk-HYRHI3QU.js";
86
+ } from "./chunk-5UIKSPDD.js";
87
87
  import {
88
88
  loadRepoSettings,
89
89
  loadWorkspaceSettings,
@@ -311,12 +311,20 @@ function diffFromInput(input) {
311
311
  }
312
312
  function parseDiffStat(result) {
313
313
  if (!result) return {};
314
- const plus = result.match(/\+(\d+)/);
315
- const minus = result.match(/-(\d+)/);
316
- if (plus || minus) {
314
+ const paired = result.match(/\+(\d+)\s+-(\d+)/);
315
+ if (paired) {
317
316
  return {
318
- additions: plus ? Number(plus[1]) : void 0,
319
- deletions: minus ? Number(minus[1]) : void 0
317
+ additions: Number(paired[1]),
318
+ deletions: Number(paired[2])
319
+ };
320
+ }
321
+ const verbose = result.match(
322
+ /(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
323
+ );
324
+ if (verbose) {
325
+ return {
326
+ additions: Number(verbose[1]),
327
+ deletions: verbose[2] != null ? Number(verbose[2]) : void 0
320
328
  };
321
329
  }
322
330
  return {};
@@ -388,8 +396,8 @@ function applyAgentEvent(parts, event) {
388
396
  ...p,
389
397
  status: event.isError ? "error" : "done",
390
398
  result: event.content,
391
- additions: fromResult.additions ?? p.additions,
392
- deletions: fromResult.deletions ?? p.deletions
399
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
400
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
393
401
  };
394
402
  });
395
403
  return next;
@@ -451,9 +459,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
451
459
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
452
460
  );
453
461
  }
454
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-QSRP25HQ.js");
462
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-4GVWSCEX.js");
455
463
  if (isGlobalThread2(thread)) {
456
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-WIYQVMOG.js");
464
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-FAILHO4J.js");
457
465
  ensureGlobalCoordinatorCwd2();
458
466
  }
459
467
  const adapter = getAdapter(thread.agent);
@@ -2606,7 +2614,7 @@ async function createThread(input, onSetupLine) {
2606
2614
  return readThread(thread.id) ?? thread;
2607
2615
  }
2608
2616
  async function listLinearIssues(agent, repoPath) {
2609
- const { getAdapter: getAdapter2 } = await import("./agents-DDW4NBBW.js");
2617
+ const { getAdapter: getAdapter2 } = await import("./agents-T6XHC5OV.js");
2610
2618
  await requireAgent(agent, { requireLinear: true });
2611
2619
  const adapter = getAdapter2(agent);
2612
2620
  if (!adapter.listLinearIssues) {
@@ -2826,7 +2834,7 @@ async function adoptThread(input) {
2826
2834
  messages: input.messages ?? []
2827
2835
  });
2828
2836
  writeThread(thread);
2829
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-DMYWHVJC.js");
2837
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-Z7CSL4O6.js");
2830
2838
  await ensureWorkspace2(repoPath);
2831
2839
  return thread;
2832
2840
  }
@@ -3288,6 +3296,15 @@ async function syncThreadBranchFromGit(threadId) {
3288
3296
  }
3289
3297
 
3290
3298
  // src/orchestrator/orchestrator.ts
3299
+ function isPidAlive(pid) {
3300
+ if (!Number.isFinite(pid) || pid <= 0) return false;
3301
+ try {
3302
+ process.kill(pid, 0);
3303
+ return true;
3304
+ } catch {
3305
+ return false;
3306
+ }
3307
+ }
3291
3308
  var Orchestrator = class {
3292
3309
  events = new EventEmitter();
3293
3310
  processes = /* @__PURE__ */ new Map();
@@ -3324,8 +3341,18 @@ var Orchestrator = class {
3324
3341
  isStaleRunningThread(threadId, status) {
3325
3342
  return status === "running" && !this.activeTurns.has(threadId) && !this.startingTurns.has(threadId);
3326
3343
  }
3344
+ /**
3345
+ * Cross-process guard: another Sideboard process (MCP stdio) may call reconcile
3346
+ * while the desktop still owns a live agent child. Never reclaim those.
3347
+ */
3348
+ shouldReclaimRunningThread(thread) {
3349
+ if (!this.isStaleRunningThread(thread.id, thread.status)) return false;
3350
+ const pid = thread.agentPid;
3351
+ if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
3352
+ return true;
3353
+ }
3327
3354
  async reconcile(repoPath, opts) {
3328
- const reclaimStaleTurns = opts?.reclaimStaleTurns !== false;
3355
+ const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
3329
3356
  healOrchestrationSoccerTitles();
3330
3357
  for (const thread of listThreads({ includeArchived: true })) {
3331
3358
  if (thread.status === "archived") continue;
@@ -3341,7 +3368,7 @@ var Orchestrator = class {
3341
3368
  if (Object.keys(heal).length) {
3342
3369
  updateThread(thread.id, heal);
3343
3370
  }
3344
- if (reclaimStaleTurns && this.isStaleRunningThread(thread.id, thread.status)) {
3371
+ if (reclaimStaleTurns && this.shouldReclaimRunningThread(thread)) {
3345
3372
  setStatus(thread.id, "stopped", "Process died (reconciled on startup)");
3346
3373
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
3347
3374
  }
@@ -3352,7 +3379,7 @@ var Orchestrator = class {
3352
3379
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
3353
3380
  continue;
3354
3381
  }
3355
- if (reclaimStaleTurns && this.isStaleRunningThread(thread.id, thread.status)) {
3382
+ if (reclaimStaleTurns && this.shouldReclaimRunningThread(thread)) {
3356
3383
  setStatus(thread.id, "stopped", "Process died (reconciled on startup)");
3357
3384
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
3358
3385
  }
@@ -3534,6 +3561,11 @@ var Orchestrator = class {
3534
3561
  await new Promise((r) => setTimeout(r, 100));
3535
3562
  continue;
3536
3563
  }
3564
+ const livePid = thread.agentPid;
3565
+ if (typeof livePid === "number" && livePid > 0 && isPidAlive(livePid)) {
3566
+ await new Promise((r) => setTimeout(r, 200));
3567
+ continue;
3568
+ }
3537
3569
  const prompt = thread.queue[0];
3538
3570
  const remaining = thread.queue.slice(1);
3539
3571
  updateThread(threadId, { queue: remaining });
@@ -3677,10 +3709,18 @@ var Orchestrator = class {
3677
3709
  if (event.type === "stderr" && typeof event.data === "string") {
3678
3710
  pushTurnStderr(stderrTail, event.data);
3679
3711
  }
3712
+ const live = readThread(threadId);
3713
+ if (live?.lastError?.includes("reconciled on startup") && (this.activeTurns.has(threadId) || this.startingTurns.has(threadId))) {
3714
+ setStatus(threadId, "running");
3715
+ this.emit({ type: "status_changed", threadId, status: "running" });
3716
+ }
3680
3717
  }
3681
3718
  );
3682
3719
  this.activeTurns.set(threadId, handle);
3683
3720
  this.startingTurns.delete(threadId);
3721
+ if (typeof handle.pid === "number" && handle.pid > 0) {
3722
+ updateThread(threadId, { agentPid: handle.pid });
3723
+ }
3684
3724
  if (this.stoppedTurns.has(threadId)) {
3685
3725
  handle.kill();
3686
3726
  } else {
@@ -3700,20 +3740,41 @@ var Orchestrator = class {
3700
3740
  if (result.sessionId) {
3701
3741
  updateThread(threadId, { sessionId: result.sessionId });
3702
3742
  }
3703
- const assistantText = result.assistantText.trim();
3704
- const failureOnlyMessage = result.exitCode !== 0 && looksLikeAgentFailureMessage(assistantText) && !result.parts.some((p) => p.type === "tool" || p.type === "thinking");
3705
- if (!failureOnlyMessage && (assistantText || result.parts.length > 0)) {
3743
+ let assistantText = result.assistantText.trim();
3744
+ let parts = result.parts;
3745
+ let usage = result.usage ?? void 0;
3746
+ let exitCode = result.exitCode;
3747
+ if (this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
3748
+ const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
3749
+ if (sessionId) {
3750
+ const { recoverFinishedCursorRun } = await import("./cursor-recover-L5PNQUDT.js");
3751
+ for (let i = 0; i < 8; i++) {
3752
+ const recovered = recoverFinishedCursorRun({
3753
+ agentId: sessionId,
3754
+ startedAfterMs: turnStartedAt - 5e3
3755
+ });
3756
+ if (recovered?.result) {
3757
+ assistantText = recovered.result;
3758
+ exitCode = 0;
3759
+ break;
3760
+ }
3761
+ await new Promise((r) => setTimeout(r, 500));
3762
+ }
3763
+ }
3764
+ }
3765
+ const failureOnlyMessage = exitCode !== 0 && looksLikeAgentFailureMessage(assistantText) && !parts.some((p) => p.type === "tool" || p.type === "thinking");
3766
+ if (!failureOnlyMessage && (assistantText || parts.length > 0)) {
3706
3767
  appendMessage(threadId, {
3707
3768
  role: "agent",
3708
3769
  text: assistantText,
3709
- parts: result.parts.length > 0 ? result.parts : void 0,
3770
+ parts: parts.length > 0 ? parts : void 0,
3710
3771
  durationMs: Math.max(0, Date.now() - turnStartedAt),
3711
- usage: result.usage ?? void 0,
3772
+ usage,
3712
3773
  ts: (/* @__PURE__ */ new Date()).toISOString()
3713
3774
  });
3714
3775
  }
3715
3776
  const afterTurn = this.requireThread(threadId);
3716
- if (afterTurn.planMode && afterTurn.agent === "claude" && result.parts.some(
3777
+ if (afterTurn.planMode && afterTurn.agent === "claude" && parts.some(
3717
3778
  (p) => p.type === "tool" && /exitplanmode/i.test(p.name)
3718
3779
  )) {
3719
3780
  updateThread(threadId, { sessionId: null });
@@ -3722,22 +3783,22 @@ var Orchestrator = class {
3722
3783
  if (this.stoppedTurns.has(threadId)) {
3723
3784
  setStatus(threadId, "stopped");
3724
3785
  this.emit({ type: "status_changed", threadId, status: "stopped" });
3725
- this.emit({ type: "turn_finished", threadId, exitCode: result.exitCode });
3786
+ this.emit({ type: "turn_finished", threadId, exitCode });
3726
3787
  } else {
3727
3788
  const lastStderr = summarizeTurnStderr(stderrTail);
3728
- const detail = lastStderr || (result.exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
3729
- const failDetail = formatTurnExitError(result.exitCode, detail);
3789
+ const detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
3790
+ const failDetail = formatTurnExitError(exitCode, detail);
3730
3791
  setStatus(
3731
3792
  threadId,
3732
- result.exitCode === 0 ? "idle" : "error",
3733
- result.exitCode === 0 ? null : failDetail
3793
+ exitCode === 0 ? "idle" : "error",
3794
+ exitCode === 0 ? null : failDetail
3734
3795
  );
3735
3796
  this.emit({
3736
3797
  type: "status_changed",
3737
3798
  threadId,
3738
- status: result.exitCode === 0 ? "idle" : "error"
3799
+ status: exitCode === 0 ? "idle" : "error"
3739
3800
  });
3740
- this.emit({ type: "turn_finished", threadId, exitCode: result.exitCode });
3801
+ this.emit({ type: "turn_finished", threadId, exitCode });
3741
3802
  }
3742
3803
  } catch (err) {
3743
3804
  const message = err instanceof Error ? err.message : String(err);
@@ -3758,6 +3819,10 @@ var Orchestrator = class {
3758
3819
  this.processes.delete(`${threadId}:agent`);
3759
3820
  this.stoppedTurns.delete(threadId);
3760
3821
  this.runningCount = Math.max(0, this.runningCount - 1);
3822
+ try {
3823
+ updateThread(threadId, { agentPid: null });
3824
+ } catch {
3825
+ }
3761
3826
  }
3762
3827
  }
3763
3828
  /**
@@ -4331,7 +4396,7 @@ var Orchestrator = class {
4331
4396
  return setStatus(thread.id, "idle");
4332
4397
  }
4333
4398
  if (!existsSync11(thread.worktreePath)) {
4334
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-37FBII5A.js");
4399
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-M3DTPYBW.js");
4335
4400
  const { execa: execa6 } = await import("execa");
4336
4401
  const slug = thread.worktreePath.split("/").pop();
4337
4402
  const dest = thread.worktreePath;
@@ -4414,7 +4479,7 @@ async function startOrchestration(opts) {
4414
4479
  sourceRef: "default",
4415
4480
  ...createOpts
4416
4481
  }).catch(async () => {
4417
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-37FBII5A.js");
4482
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-M3DTPYBW.js");
4418
4483
  const repo = await resolveRepoRoot2(repoPath);
4419
4484
  const def = await resolveDefaultBranch2(repo);
4420
4485
  return createThread({
@@ -4424,7 +4489,7 @@ async function startOrchestration(opts) {
4424
4489
  repoPath: repo
4425
4490
  });
4426
4491
  });
4427
- const { updateThread: upd } = await import("./thread-store-UNPZNIFW.js");
4492
+ const { updateThread: upd } = await import("./thread-store-WPLT3IXM.js");
4428
4493
  const updated = upd(thread.id, {
4429
4494
  sourceType: "orchestration",
4430
4495
  sourceRef: goal
@@ -5107,6 +5172,7 @@ export {
5107
5172
  worktreeCleanupSettings,
5108
5173
  applyThreadIntoMain,
5109
5174
  cloneRepoIntoSideboard,
5175
+ isPidAlive,
5110
5176
  Orchestrator,
5111
5177
  getOrchestrator,
5112
5178
  startOrchestration,
@@ -6,9 +6,9 @@ import {
6
6
  enrichWorkspacesWithGithub,
7
7
  ensureGlobalCoordinatorCwd,
8
8
  formatWorkspaceInventory
9
- } from "./chunk-PTASB7SJ.js";
10
- import "./chunk-XBEQI5H4.js";
11
- import "./chunk-HYRHI3QU.js";
9
+ } from "./chunk-UPMGXM4X.js";
10
+ import "./chunk-VA2U5EQH.js";
11
+ import "./chunk-5UIKSPDD.js";
12
12
  import "./chunk-M37RITA6.js";
13
13
  import "./chunk-AJ6ROGD7.js";
14
14
  export {
@@ -0,0 +1,42 @@
1
+ import {
2
+ appDataDir
3
+ } from "./chunk-M37RITA6.js";
4
+
5
+ // src/agents/cursor-recover.ts
6
+ import { existsSync, readFileSync } from "fs";
7
+ import { join } from "path";
8
+ function recoverFinishedCursorRun(opts) {
9
+ const agentId = opts.agentId.trim();
10
+ if (!agentId) return null;
11
+ const runsPath = join(appDataDir(), "cursor-sdk-store", "runs.ndjson");
12
+ if (!existsSync(runsPath)) return null;
13
+ try {
14
+ const lines = readFileSync(runsPath, "utf8").split("\n");
15
+ let best = null;
16
+ for (const line of lines) {
17
+ const trimmed = line.trim();
18
+ if (!trimmed) continue;
19
+ let row;
20
+ try {
21
+ row = JSON.parse(trimmed);
22
+ } catch {
23
+ continue;
24
+ }
25
+ if (row.agentId !== agentId) continue;
26
+ if (row.status !== "finished") continue;
27
+ if (typeof row.result !== "string" || !row.result.trim()) continue;
28
+ const endedAt = typeof row.endedAt === "number" ? row.endedAt : 0;
29
+ const createdAt = typeof row.createdAt === "number" ? row.createdAt : 0;
30
+ if (createdAt < opts.startedAfterMs && endedAt < opts.startedAfterMs) continue;
31
+ if (!best || endedAt >= best.endedAt) {
32
+ best = { runId: row.runId || "", result: row.result.trim(), endedAt };
33
+ }
34
+ }
35
+ return best;
36
+ } catch {
37
+ return null;
38
+ }
39
+ }
40
+ export {
41
+ recoverFinishedCursorRun
42
+ };
@@ -11,10 +11,10 @@ import {
11
11
  orchestrationTitleNeedsSoccerNickname,
12
12
  orchestratorSessionPoisonedByBuiltins,
13
13
  takenTeamSlugsForOrchestration
14
- } from "./chunk-IS3AGU33.js";
15
- import "./chunk-PTASB7SJ.js";
16
- import "./chunk-XBEQI5H4.js";
17
- import "./chunk-HYRHI3QU.js";
14
+ } from "./chunk-6TZSJMXF.js";
15
+ import "./chunk-UPMGXM4X.js";
16
+ import "./chunk-VA2U5EQH.js";
17
+ import "./chunk-5UIKSPDD.js";
18
18
  import {
19
19
  globalAgentCwd
20
20
  } from "./chunk-M37RITA6.js";