@sideboard-ai/core 0.1.99 → 0.1.103

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.
Files changed (52) hide show
  1. package/dist/agents/cursor-runner.cjs +22 -22
  2. package/dist/agents/cursor-runner.js +2 -2
  3. package/dist/{agents-ESJKIQQA.js → agents-UT5GCJH3.js} +8 -8
  4. package/dist/{agents-3MWWWSMF.js → agents-XZBAKBO2.js} +9 -9
  5. package/dist/{app-settings-BRF7VKTQ.js → app-settings-EKJM2344.js} +2 -2
  6. package/dist/{app-settings-ZXPAB3QN.js → app-settings-VDJK2BZ2.js} +2 -2
  7. package/dist/{caffeinate-hold-U3QJBV67.js → caffeinate-hold-NBRUWYXO.js} +2 -2
  8. package/dist/{caffeinate-hold-I7SG6UQR.js → caffeinate-hold-X3JNPR42.js} +2 -2
  9. package/dist/{chunk-UYQYK2RY.js → chunk-27MCESES.js} +3 -3
  10. package/dist/{chunk-QSLE4VEM.js → chunk-2GO3YKBA.js} +4 -4
  11. package/dist/{chunk-DKHGWYWR.js → chunk-7YKXHBIW.js} +1 -1
  12. package/dist/{chunk-JL4SJ6V7.js → chunk-BD2ICC4D.js} +4 -0
  13. package/dist/{chunk-NZPGMNFC.js → chunk-DCOZABNT.js} +1 -1
  14. package/dist/{chunk-CIRXAYWS.js → chunk-DHAGMJIK.js} +55 -28
  15. package/dist/{chunk-XUWDLRAE.js → chunk-ETMRBJKA.js} +11 -11
  16. package/dist/{chunk-MBP3XG57.js → chunk-H6LP57EF.js} +7 -7
  17. package/dist/{chunk-FO67IJTY.js → chunk-HHLZWO7U.js} +5 -5
  18. package/dist/{chunk-GXSYI7FH.js → chunk-HUKCGRAT.js} +209 -59
  19. package/dist/{chunk-3WA37BRI.js → chunk-KGSVLZV6.js} +11 -4
  20. package/dist/{chunk-7KDBDMNC.js → chunk-KLBOWJ74.js} +1 -1
  21. package/dist/{chunk-FYS2BULQ.js → chunk-LANDJIAI.js} +213 -63
  22. package/dist/{chunk-OANJQTVG.js → chunk-ND6AO7C5.js} +3 -3
  23. package/dist/{chunk-HI2OTFFR.js → chunk-OW34MVDN.js} +5 -5
  24. package/dist/{chunk-JOF3XIEM.js → chunk-P3BQ5DOL.js} +11 -4
  25. package/dist/{chunk-B4R2VB2A.js → chunk-QZQEXME2.js} +4 -0
  26. package/dist/{chunk-R7BQBSDT.js → chunk-WA3DVVWG.js} +55 -28
  27. package/dist/{chunk-6LFV4VFI.js → chunk-WSYCND2U.js} +1 -1
  28. package/dist/{chunk-FT2SQOL4.js → chunk-XHZJJWLI.js} +1 -1
  29. package/dist/{chunk-XH2GS2LO.js → chunk-YJADJH5U.js} +11 -11
  30. package/dist/{connected-teams-SWHJWK2A.js → connected-teams-J4I5AKMR.js} +2 -2
  31. package/dist/{connected-teams-TLVKZPJP.js → connected-teams-M5XNXRI5.js} +2 -2
  32. package/dist/{coordinator-prompt-OQOOD5ET.js → coordinator-prompt-3DFZRMXE.js} +5 -5
  33. package/dist/{coordinator-prompt-AKEY4WSO.js → coordinator-prompt-UWHSD65V.js} +5 -5
  34. package/dist/{cursor-recover-S5ORPW34.js → cursor-recover-JBTIDARH.js} +1 -1
  35. package/dist/{cursor-recover-G34BYKL2.js → cursor-recover-ZUJG6XRQ.js} +1 -1
  36. package/dist/{global-workspace-WMF3BJP5.js → global-workspace-KJQS5S2C.js} +6 -6
  37. package/dist/{global-workspace-RSQXRLT7.js → global-workspace-UR4E3CCG.js} +6 -6
  38. package/dist/index.cjs +851 -232
  39. package/dist/index.d.cts +39 -6
  40. package/dist/index.d.ts +39 -6
  41. package/dist/index.js +561 -138
  42. package/dist/mcp/run-stdio.cjs +651 -256
  43. package/dist/mcp/run-stdio.js +345 -143
  44. package/dist/{paths-TZX4L5X7.js → paths-QCI3MTO5.js} +3 -1
  45. package/dist/{paths-JQM2XRAD.js → paths-UMEDHOS5.js} +3 -1
  46. package/dist/{thread-store-XAKWCV2E.js → thread-store-4OUEQ2DB.js} +2 -2
  47. package/dist/{thread-store-V7NOOXKE.js → thread-store-DQJGDKIJ.js} +2 -2
  48. package/dist/{workspaces-MZVQHRSJ.js → workspaces-NTIVI6DI.js} +7 -7
  49. package/dist/{workspaces-4ZY4QPWQ.js → workspaces-TKJXPNV4.js} +7 -7
  50. package/dist/{worktree-EO5QAGJU.js → worktree-NKWN5ZTS.js} +4 -4
  51. package/dist/{worktree-DA4BOV7G.js → worktree-PEUPFAKL.js} +4 -4
  52. package/package.json +2 -2
@@ -75,7 +75,15 @@ function looksLikeMinifiedJsDump(line) {
75
75
  function looksLikeNestedElectronCrash(line) {
76
76
  return /HasCustomHostObject|ElectronInitializeICUandStartNode/i.test(line);
77
77
  }
78
+ function looksLikeHomebrewLibuvCrash(line) {
79
+ const uvRun = /uv_run/i.test(line);
80
+ const spin = /SpinEventLoopInternal/i.test(line);
81
+ const homebrewUv = /Cellar\/libuv|libuv\.\d\.dylib/i.test(line);
82
+ const homebrewNode = /Cellar\/node\//i.test(line);
83
+ return uvRun && (homebrewUv || spin || homebrewNode) || spin && (homebrewUv || homebrewNode);
84
+ }
78
85
  var NESTED_ELECTRON_SUMMARY = "Cursor local agent crashed at Electron startup (nested Chromium / HasCustomHostObject)";
86
+ var HOMEBREW_LIBUV_SUMMARY = "Cursor runner crashed in Node (Homebrew Node + shared libuv). Install Node 22 LTS (`brew install node@22`) and retry.";
79
87
  var MINIFIED_DUMP_SUMMARY = "Cursor local agent crashed during startup (truncated crash dump)";
80
88
  function clipStderr(text, maxChars) {
81
89
  const trimmed = text.trim();
@@ -87,6 +95,7 @@ function summarizeTurnStderr(tail, maxChars = 500) {
87
95
  const cursorStartup = [...tail].reverse().find((line) => /cursor startup failed:/i.test(line));
88
96
  if (cursorStartup) return clipStderr(cursorStartup, maxChars);
89
97
  if (tail.some(looksLikeNestedElectronCrash)) return NESTED_ELECTRON_SUMMARY;
98
+ if (tail.some(looksLikeHomebrewLibuvCrash)) return HOMEBREW_LIBUV_SUMMARY;
90
99
  if (tail.some(
91
100
  (line) => /\[resource_exhausted\]|resource_exhausted/i.test(line) || /findFilesWithRipgrep/.test(line)
92
101
  )) {
@@ -109,6 +118,20 @@ function looksLikeInvalidAgentSession(text) {
109
118
  if (!lower) return false;
110
119
  return /session not found/.test(lower) || /no conversation found/.test(lower) || /conversation .+ not found/.test(lower) || /thread .+ not found/.test(lower) || /unknown session/.test(lower) || /invalid session/.test(lower) || /session .+ (missing|expired|deleted|gone)/.test(lower) || /cannot resume/.test(lower) || /failed to (load|resume|open) session/.test(lower) || /corrupt local agent checkpoint/.test(lower) || /missing root blob/.test(lower) || /\bagent\b.{0,120}\bnot found\b/.test(lower);
111
120
  }
121
+ function looksLikeRetryableRunnerCrash(text) {
122
+ if (looksLikeAgentFailureMessage(text)) return false;
123
+ if (looksLikeInvalidAgentSession(text)) return false;
124
+ const lower = text.trim().toLowerCase();
125
+ if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
126
+ if (!lower) return true;
127
+ return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
128
+ lower
129
+ );
130
+ }
131
+ function shouldRetryFailedAgentTurn(detail, opts) {
132
+ if (looksLikeInvalidAgentSession(detail) && opts.hasSession) return true;
133
+ return looksLikeRetryableRunnerCrash(detail);
134
+ }
112
135
  function looksLikeAgentFailureMessage(text) {
113
136
  const lower = text.trim().toLowerCase();
114
137
  if (!lower) return false;
@@ -153,11 +176,22 @@ function humanizeAgentFailDetail(detail) {
153
176
  if (/hascustomhostobject|electroninitializeicuandstartnode|nested chromium/i.test(lower)) {
154
177
  return `${raw} \u2014 retry the turn; if it keeps failing, pick another agent.`;
155
178
  }
179
+ if (/homebrew node \+ shared libuv|uv_run|spineventloopinternal/i.test(lower)) {
180
+ return /brew install node@22/i.test(raw) ? raw : `${raw} \u2014 install Node 22 LTS (\`brew install node@22\`) and retry.`;
181
+ }
156
182
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
157
183
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
158
184
  }
159
185
  return raw;
160
186
  }
187
+ function turnFailChatText(opts) {
188
+ const chat = opts.assistantText.trim();
189
+ if (chat) return chat;
190
+ if (opts.exitCode === 0) return "";
191
+ const detail = opts.detail.trim();
192
+ if (detail) return humanizeAgentFailDetail(detail);
193
+ return formatTurnExitError(opts.exitCode ?? 1, "");
194
+ }
161
195
  function formatTurnExitError(exitCode, stderrSummary) {
162
196
  const code = exitCode ?? 1;
163
197
  const raw = stderrSummary.trim();
@@ -348,9 +382,54 @@ import { dirname, isAbsolute, join as join3, parse, resolve as resolvePath } fro
348
382
  import { fileURLToPath } from "url";
349
383
 
350
384
  // src/agents/node-launch.ts
351
- import { existsSync } from "fs";
385
+ import { existsSync as existsSync2, readdirSync, realpathSync } from "fs";
352
386
  import { homedir } from "os";
387
+ import { join as join2 } from "path";
388
+
389
+ // src/agents/packaged-runtime.ts
390
+ import { existsSync } from "fs";
353
391
  import { join } from "path";
392
+ function electronResourcesPath() {
393
+ const resources = process.resourcesPath;
394
+ if (typeof resources !== "string" || !resources) return null;
395
+ return resources;
396
+ }
397
+ function packagedCursorRuntimeDir() {
398
+ const resources = electronResourcesPath();
399
+ if (!resources) return null;
400
+ const dir = join(resources, "cursor-runtime");
401
+ if (!existsSync(join(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
402
+ return dir;
403
+ }
404
+ function packagedCursorRunnerPath() {
405
+ const dir = packagedCursorRuntimeDir();
406
+ return dir ? join(dir, "core-dist", "agents", "cursor-runner.js") : null;
407
+ }
408
+ function packagedMcpDir() {
409
+ const resources = electronResourcesPath();
410
+ if (!resources) return null;
411
+ const dir = join(resources, "sideboard-mcp");
412
+ if (!existsSync(join(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
413
+ return dir;
414
+ }
415
+ function packagedMcpStdioPath() {
416
+ const dir = packagedMcpDir();
417
+ return dir ? join(dir, "core-dist", "mcp", "run-stdio.js") : null;
418
+ }
419
+ function packagedBundledNodePath() {
420
+ const resources = electronResourcesPath();
421
+ if (!resources) return null;
422
+ const bin = join(resources, "node", "bin", "node");
423
+ if (!existsSync(bin)) return null;
424
+ return bin;
425
+ }
426
+ function packagedCursorRipgrepCandidate(platformPkg, binName) {
427
+ const dir = packagedCursorRuntimeDir();
428
+ if (!dir) return null;
429
+ return join(dir, "node_modules", platformPkg, "bin", binName);
430
+ }
431
+
432
+ // src/agents/node-launch.ts
354
433
  function isAsarPath(filePath) {
355
434
  if (/\.asar\.unpacked([/\\]|$)/.test(filePath)) return false;
356
435
  return /\.asar([/\\]|$)/.test(filePath);
@@ -359,28 +438,130 @@ function unpackedAsarPath(filePath) {
359
438
  if (!isAsarPath(filePath)) return null;
360
439
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
361
440
  if (unpacked === filePath) return null;
362
- return existsSync(unpacked) ? unpacked : null;
441
+ return existsSync2(unpacked) ? unpacked : null;
363
442
  }
364
443
  function nodeReadableScriptPath(scriptPath) {
365
444
  return unpackedAsarPath(scriptPath) ?? scriptPath;
366
445
  }
367
- var WELL_KNOWN_NODE_BINS = [
368
- "/opt/homebrew/bin/node",
369
- "/usr/local/bin/node"
370
- ];
371
- async function findSystemNode() {
372
- const whichNode = await run("which", ["node"], { reject: false });
373
- const fromWhich = whichNode.exitCode === 0 && whichNode.stdout.trim() ? whichNode.stdout.trim() : "";
374
- if (fromWhich && !isElectronLikeCommand(fromWhich)) return fromWhich;
375
- const fallbacks = [
376
- ...WELL_KNOWN_NODE_BINS,
377
- join(homedir(), ".local/share/fnm/aliases/default/bin/node"),
378
- join(homedir(), ".nvm/current/bin/node")
446
+ var PREFERRED_LTS_MAJORS = [24, 22, 20];
447
+ function parseNodeMajor(version) {
448
+ const match = /^v?(\d+)/.exec(version.trim());
449
+ if (!match) return null;
450
+ const major = Number(match[1]);
451
+ return Number.isInteger(major) ? major : null;
452
+ }
453
+ function scoreNodeForAgentRuntime(candidate) {
454
+ const major = parseNodeMajor(candidate.version);
455
+ if (major == null) return Number.NEGATIVE_INFINITY;
456
+ if (major < 20) return major - 100;
457
+ const posix = candidate.path.replace(/\\/g, "/");
458
+ let score = 0;
459
+ if (major % 2 === 0) {
460
+ score += 1e3 + major * 10;
461
+ } else {
462
+ score += major;
463
+ }
464
+ if (/\/Cellar\/node\/\d/.test(posix) && !/\/Cellar\/node@\d+/.test(posix)) {
465
+ score -= 50;
466
+ }
467
+ return score;
468
+ }
469
+ function pickPreferredNode(candidates) {
470
+ let best = null;
471
+ let bestScore = Number.NEGATIVE_INFINITY;
472
+ for (const candidate of candidates) {
473
+ const score = scoreNodeForAgentRuntime(candidate);
474
+ if (score > bestScore) {
475
+ bestScore = score;
476
+ best = candidate;
477
+ }
478
+ }
479
+ return best;
480
+ }
481
+ function versionDirNodeBins(root, toBin) {
482
+ if (!existsSync2(root)) return [];
483
+ try {
484
+ return readdirSync(root).map(toBin);
485
+ } catch {
486
+ return [];
487
+ }
488
+ }
489
+ function defaultNodeBinCandidates(home = homedir()) {
490
+ const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
491
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => join2(prefix, "opt", `node@${major}`, "bin", "node"))
492
+ );
493
+ return [
494
+ ...kegs,
495
+ "/opt/homebrew/bin/node",
496
+ "/usr/local/bin/node",
497
+ join2(home, ".local/share/fnm/aliases/default/bin/node"),
498
+ join2(home, ".nvm/current/bin/node"),
499
+ join2(home, ".volta/bin/node"),
500
+ join2(home, ".asdf/shims/node"),
501
+ join2(home, ".local/share/mise/shims/node"),
502
+ ...versionDirNodeBins(
503
+ join2(home, ".nvm", "versions", "node"),
504
+ (name) => join2(home, ".nvm", "versions", "node", name, "bin", "node")
505
+ ),
506
+ ...versionDirNodeBins(
507
+ join2(home, ".local/share/fnm", "node-versions"),
508
+ (name) => join2(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
509
+ ),
510
+ ...versionDirNodeBins(
511
+ join2(home, ".volta", "tools", "image", "node"),
512
+ (name) => join2(home, ".volta", "tools", "image", "node", name, "bin", "node")
513
+ )
379
514
  ];
380
- for (const bin of fallbacks) {
381
- if (existsSync(bin) && !isElectronLikeCommand(bin)) return bin;
515
+ }
516
+ function uniqueExistingNodeBins(paths) {
517
+ const seen = /* @__PURE__ */ new Set();
518
+ const out = [];
519
+ for (const raw of paths) {
520
+ const p = raw.trim();
521
+ if (!p || !existsSync2(p) || isElectronLikeCommand(p)) continue;
522
+ let key = p;
523
+ try {
524
+ key = realpathSync(p);
525
+ } catch {
526
+ continue;
527
+ }
528
+ if (seen.has(key)) continue;
529
+ seen.add(key);
530
+ out.push(p);
382
531
  }
383
- return null;
532
+ return out;
533
+ }
534
+ async function whichAllNode() {
535
+ if (process.platform === "win32") {
536
+ const located = await run("where", ["node"], { reject: false, timeoutMs: 5e3 });
537
+ if (located.exitCode !== 0) return [];
538
+ return located.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
539
+ }
540
+ const all = await run("which", ["-a", "node"], { reject: false, timeoutMs: 5e3 });
541
+ if (all.exitCode === 0 && all.stdout.trim()) {
542
+ return all.stdout.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
543
+ }
544
+ const single = await run("which", ["node"], { reject: false, timeoutMs: 5e3 });
545
+ if (single.exitCode !== 0 || !single.stdout.trim()) return [];
546
+ return [single.stdout.trim()];
547
+ }
548
+ async function probeNodeVersion(bin) {
549
+ const probed = await run(bin, ["-v"], { reject: false, timeoutMs: 4e3 });
550
+ if (probed.exitCode !== 0) return null;
551
+ const version = probed.stdout.trim().split(/\r?\n/).find(Boolean);
552
+ return version || null;
553
+ }
554
+ async function findSystemNode() {
555
+ const fromPath = await whichAllNode();
556
+ const bins = uniqueExistingNodeBins([...fromPath, ...defaultNodeBinCandidates()]);
557
+ if (bins.length === 0) return null;
558
+ const probed = await Promise.all(
559
+ bins.map(async (path) => {
560
+ const version = await probeNodeVersion(path);
561
+ return version ? { path, version } : null;
562
+ })
563
+ );
564
+ return pickPreferredNode(probed.filter((c) => c != null));
384
565
  }
385
566
  function applyNodeLaunch(launch, args) {
386
567
  const readableArgs = args.map(nodeReadableScriptPath);
@@ -398,9 +579,13 @@ function applyNodeLaunch(launch, args) {
398
579
  async function resolveNodeLaunch(scriptPath) {
399
580
  const script = nodeReadableScriptPath(scriptPath);
400
581
  if (!isAsarPath(script)) {
401
- const nodeBin = await findSystemNode();
402
- if (nodeBin) {
403
- return { file: nodeBin, env: {} };
582
+ const bundled = packagedBundledNodePath();
583
+ if (bundled && !isElectronLikeCommand(bundled)) {
584
+ return { file: bundled, env: {} };
585
+ }
586
+ const node = await findSystemNode();
587
+ if (node) {
588
+ return { file: node.path, env: {}, nodeVersion: node.version };
404
589
  }
405
590
  }
406
591
  return {
@@ -409,42 +594,6 @@ async function resolveNodeLaunch(scriptPath) {
409
594
  };
410
595
  }
411
596
 
412
- // src/agents/packaged-runtime.ts
413
- import { existsSync as existsSync2 } from "fs";
414
- import { join as join2 } from "path";
415
- function electronResourcesPath() {
416
- const resources = process.resourcesPath;
417
- if (typeof resources !== "string" || !resources) return null;
418
- return resources;
419
- }
420
- function packagedCursorRuntimeDir() {
421
- const resources = electronResourcesPath();
422
- if (!resources) return null;
423
- const dir = join2(resources, "cursor-runtime");
424
- if (!existsSync2(join2(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
425
- return dir;
426
- }
427
- function packagedCursorRunnerPath() {
428
- const dir = packagedCursorRuntimeDir();
429
- return dir ? join2(dir, "core-dist", "agents", "cursor-runner.js") : null;
430
- }
431
- function packagedMcpDir() {
432
- const resources = electronResourcesPath();
433
- if (!resources) return null;
434
- const dir = join2(resources, "sideboard-mcp");
435
- if (!existsSync2(join2(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
436
- return dir;
437
- }
438
- function packagedMcpStdioPath() {
439
- const dir = packagedMcpDir();
440
- return dir ? join2(dir, "core-dist", "mcp", "run-stdio.js") : null;
441
- }
442
- function packagedCursorRipgrepCandidate(platformPkg, binName) {
443
- const dir = packagedCursorRuntimeDir();
444
- if (!dir) return null;
445
- return join2(dir, "node_modules", platformPkg, "bin", binName);
446
- }
447
-
448
597
  // src/agents/cursor-ripgrep.ts
449
598
  var RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
450
599
  function rgBinaryName() {
@@ -512,15 +661,16 @@ export {
512
661
  pushTurnStderr,
513
662
  summarizeTurnStderr,
514
663
  looksLikeInvalidAgentSession,
664
+ shouldRetryFailedAgentTurn,
515
665
  looksLikeAgentFailureMessage,
516
666
  fallbackTurnFailDetail,
517
- humanizeAgentFailDetail,
667
+ turnFailChatText,
518
668
  formatTurnExitError,
669
+ packagedCursorRunnerPath,
670
+ packagedMcpStdioPath,
519
671
  isAsarPath,
520
672
  applyNodeLaunch,
521
673
  resolveNodeLaunch,
522
- packagedCursorRunnerPath,
523
- packagedMcpStdioPath,
524
674
  cursorSdkMessageToEvents,
525
675
  parseCursorRunnerLine,
526
676
  cursorRipgrepEnv,
@@ -5,7 +5,7 @@ import {
5
5
  threadFilePath,
6
6
  threadLockPath,
7
7
  threadsDir
8
- } from "./chunk-B4R2VB2A.js";
8
+ } from "./chunk-QZQEXME2.js";
9
9
 
10
10
  // src/store/thread-store.ts
11
11
  import { randomUUID } from "crypto";
@@ -117,8 +117,11 @@ function writeThread(thread) {
117
117
  function idPath(id) {
118
118
  return id;
119
119
  }
120
+ function isThreadRecordFile(name) {
121
+ return name.endsWith(".json") && !name.endsWith(".live.json");
122
+ }
120
123
  function listThreads(opts) {
121
- const files = readdirSync(threadsDir()).filter((f) => f.endsWith(".json"));
124
+ const files = readdirSync(threadsDir()).filter(isThreadRecordFile);
122
125
  const threads = files.map((f) => {
123
126
  try {
124
127
  return normalizeThread(
@@ -127,7 +130,9 @@ function listThreads(opts) {
127
130
  } catch {
128
131
  return null;
129
132
  }
130
- }).filter((t) => t !== null).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
133
+ }).filter(
134
+ (t) => t !== null && typeof t.id === "string" && t.id.length > 0
135
+ ).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
131
136
  if (opts?.includeArchived) return threads;
132
137
  return threads.filter((t) => t.status !== "archived");
133
138
  }
@@ -159,7 +164,9 @@ function setStatus(id, status, lastError) {
159
164
  }
160
165
  function findThreadByRef(ref) {
161
166
  const all = listThreads({ includeArchived: true });
162
- return all.find((t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref) ?? null;
167
+ return all.find(
168
+ (t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
169
+ ) ?? null;
163
170
  }
164
171
 
165
172
  export {
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-NSTQ6QKD.js";
6
6
  import {
7
7
  appDataDir
8
- } from "./chunk-JL4SJ6V7.js";
8
+ } from "./chunk-BD2ICC4D.js";
9
9
 
10
10
  // src/store/caffeinate-hold.ts
11
11
  import { spawn } from "child_process";