@sideboard-ai/core 0.1.196 → 0.1.198

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.
@@ -25,11 +25,12 @@ import {
25
25
  formatUnknownDetail,
26
26
  isAsarPath,
27
27
  looksLikeAgentFailureMessage,
28
+ looksLikeBrightsyEmptyCompletion,
28
29
  packagedCursorRunnerPath,
29
30
  packagedMcpStdioPath,
30
31
  parseCursorRunnerLine,
31
32
  resolveNodeLaunch
32
- } from "./chunk-NLHFAMC2.js";
33
+ } from "./chunk-CQ5R3VPP.js";
33
34
  import {
34
35
  claudeChromeEnabled,
35
36
  isAbleTimeConnected,
@@ -268,6 +269,12 @@ function parseBrightsyCliLine(line) {
268
269
  try {
269
270
  const obj = JSON.parse(trimmed);
270
271
  if (obj.type === "text" && typeof obj.text === "string") {
272
+ if (looksLikeBrightsyEmptyCompletion(obj.text)) {
273
+ return [
274
+ { type: "stderr", data: obj.text },
275
+ { type: "stdout", data: `Error: ${obj.text}` }
276
+ ];
277
+ }
271
278
  return { type: "stdout", data: obj.text };
272
279
  }
273
280
  if (obj.type === "thinking" && typeof obj.text === "string") {
@@ -311,7 +318,7 @@ function parseBrightsyCliLine(line) {
311
318
  if (trimmed.startsWith("{") && /"type"\s*:\s*"(tool_use|tool_result|tool|text|thinking|usage|done|error)"/.test(trimmed)) {
312
319
  return null;
313
320
  }
314
- if (/error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
321
+ if (looksLikeBrightsyEmptyCompletion(trimmed) || /error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
315
322
  return [
316
323
  { type: "stderr", data: trimmed },
317
324
  { type: "stdout", data: `Error: ${trimmed}` }
@@ -320,6 +327,12 @@ function parseBrightsyCliLine(line) {
320
327
  return { type: "stdout", data: line };
321
328
  }
322
329
  }
330
+ function adjustBrightsyTurnExit(exitCode, assistantText) {
331
+ if (looksLikeBrightsyEmptyCompletion(assistantText) && (exitCode === 0 || exitCode == null)) {
332
+ return 2;
333
+ }
334
+ return exitCode;
335
+ }
323
336
  async function fetchTeamChatTargets(team) {
324
337
  const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
325
338
  let agents = [
@@ -605,11 +618,18 @@ function clipChatLine(value, max = CHAT_DETAIL_MAX) {
605
618
  if (line.length <= max) return line;
606
619
  return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
607
620
  }
621
+ var SHELL_BIN_DIR = /^(?:\/usr\/local\/bin|\/usr\/bin|\/bin|\/opt\/homebrew\/bin|\/sbin|\/usr\/sbin)\//;
622
+ function rootedPathWithSpaces(trimmed) {
623
+ const [head = "", ...rest] = trimmed.split(/\s+/);
624
+ if (SHELL_BIN_DIR.test(head)) return false;
625
+ return rest.every((tok) => !/^[-/~$]/.test(tok) && !tok.includes("="));
626
+ }
608
627
  function looksLikeFilePath(value) {
609
628
  const trimmed = value.trim();
610
- if (!trimmed || /[\s;|&<>]/.test(trimmed)) return false;
611
- if (trimmed.startsWith("/") || trimmed.startsWith("~/")) return true;
612
- if (/^[A-Za-z]:[\\/]/.test(trimmed)) return true;
629
+ if (!trimmed || /[\r\n;|&<>]/.test(trimmed)) return false;
630
+ const rooted = trimmed.startsWith("/") || trimmed.startsWith("~/") || /^[A-Za-z]:[\\/]/.test(trimmed);
631
+ if (/\s/.test(trimmed)) return rooted && rootedPathWithSpaces(trimmed);
632
+ if (rooted) return true;
613
633
  return trimmed.includes("/") || trimmed.includes("\\");
614
634
  }
615
635
  function stripWorktreePrefix(path, worktreePath) {
@@ -934,6 +954,12 @@ function parseDiffStat(result) {
934
954
  }
935
955
  return {};
936
956
  }
957
+ var THINKING_PART_MAX_CHARS = 64e3;
958
+ function clipThinkingForStore(text, max = THINKING_PART_MAX_CHARS) {
959
+ if (text.length <= max) return text;
960
+ const marker = "\u2026(earlier thinking trimmed)\n";
961
+ return marker + text.slice(text.length - Math.max(1, max - marker.length));
962
+ }
937
963
  function withPartTimes(next, prev) {
938
964
  const now = Date.now();
939
965
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
@@ -976,7 +1002,7 @@ function applyAgentEvent(parts, event) {
976
1002
  next[i] = withPartTimes(
977
1003
  {
978
1004
  type: "thinking",
979
- text: data,
1005
+ text: clipThinkingForStore(data),
980
1006
  ...event.parentId ? { parentId: event.parentId } : {}
981
1007
  },
982
1008
  prev
@@ -987,7 +1013,7 @@ function applyAgentEvent(parts, event) {
987
1013
  next.push(
988
1014
  withPartTimes({
989
1015
  type: "thinking",
990
- text: data,
1016
+ text: clipThinkingForStore(data),
991
1017
  ...event.parentId ? { parentId: event.parentId } : {}
992
1018
  })
993
1019
  );
@@ -998,7 +1024,7 @@ function applyAgentEvent(parts, event) {
998
1024
  next[next.length - 1] = withPartTimes(
999
1025
  {
1000
1026
  type: "thinking",
1001
- text: last.text + data,
1027
+ text: clipThinkingForStore(last.text + data),
1002
1028
  ...event.parentId ? { parentId: event.parentId } : {}
1003
1029
  },
1004
1030
  last
@@ -3665,6 +3691,7 @@ export {
3665
3691
  countCacheControlBlocks,
3666
3692
  MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
3667
3693
  parseBrightsyCliLine,
3694
+ adjustBrightsyTurnExit,
3668
3695
  listBrightsyChatTargets,
3669
3696
  brightsyAdapter,
3670
3697
  parseMcpList,
@@ -3684,6 +3711,8 @@ export {
3684
3711
  withEventParentId,
3685
3712
  withEventsParentId,
3686
3713
  toolFilePath,
3714
+ THINKING_PART_MAX_CHARS,
3715
+ clipThinkingForStore,
3687
3716
  applyAgentEvent,
3688
3717
  partsToAssistantText,
3689
3718
  lastAssistantMessageText,
@@ -350,11 +350,20 @@ function looksLikeInvalidAgentSession(text) {
350
350
  if (!lower) return false;
351
351
  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) || /\brun\b.{0,80}\bnot found for agent\b/.test(lower);
352
352
  }
353
+ function looksLikeCursorHttp2StreamClose(text) {
354
+ return /nghttp2/i.test(text.trim());
355
+ }
356
+ function looksLikeBrightsyEmptyCompletion(text) {
357
+ const core = text.trim().replace(/^exit\s*\d+:\s*/i, "").replace(/^error:\s*/i, "").trim();
358
+ return /^i did not receive a valid model response\. please try again\.$/i.test(core);
359
+ }
353
360
  function looksLikeRetryableRunnerCrash(text) {
354
361
  if (looksLikeAgentFailureMessage(text)) return false;
355
362
  if (looksLikeInvalidAgentSession(text)) return false;
356
363
  if (looksLikeV8Oom(text)) return false;
357
364
  if (looksLikeHugeToolResultDump(text)) return true;
365
+ if (looksLikeCursorHttp2StreamClose(text)) return true;
366
+ if (looksLikeBrightsyEmptyCompletion(text)) return true;
358
367
  const lower = text.trim().toLowerCase();
359
368
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
360
369
  if (!lower) return true;
@@ -427,9 +436,12 @@ function humanizeAgentFailDetail(detail) {
427
436
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
428
437
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
429
438
  }
430
- if (/connection stalled/.test(lower)) {
439
+ if (/connection stalled/.test(lower) || looksLikeCursorHttp2StreamClose(raw)) {
431
440
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
432
441
  }
442
+ if (looksLikeBrightsyEmptyCompletion(raw)) {
443
+ return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Brightsy returned an empty model completion).`;
444
+ }
433
445
  if (/network request failed|cursor startup failed:.+\(retryable\)/.test(lower)) {
434
446
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (a transient Cursor SDK network error).`;
435
447
  }
@@ -546,6 +558,12 @@ function parseBrightsyCliLine(line) {
546
558
  try {
547
559
  const obj = JSON.parse(trimmed);
548
560
  if (obj.type === "text" && typeof obj.text === "string") {
561
+ if (looksLikeBrightsyEmptyCompletion(obj.text)) {
562
+ return [
563
+ { type: "stderr", data: obj.text },
564
+ { type: "stdout", data: `Error: ${obj.text}` }
565
+ ];
566
+ }
549
567
  return { type: "stdout", data: obj.text };
550
568
  }
551
569
  if (obj.type === "thinking" && typeof obj.text === "string") {
@@ -589,7 +607,7 @@ function parseBrightsyCliLine(line) {
589
607
  if (trimmed.startsWith("{") && /"type"\s*:\s*"(tool_use|tool_result|tool|text|thinking|usage|done|error)"/.test(trimmed)) {
590
608
  return null;
591
609
  }
592
- if (/error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
610
+ if (looksLikeBrightsyEmptyCompletion(trimmed) || /error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
593
611
  return [
594
612
  { type: "stderr", data: trimmed },
595
613
  { type: "stdout", data: `Error: ${trimmed}` }
@@ -598,6 +616,12 @@ function parseBrightsyCliLine(line) {
598
616
  return { type: "stdout", data: line };
599
617
  }
600
618
  }
619
+ function adjustBrightsyTurnExit(exitCode, assistantText) {
620
+ if (looksLikeBrightsyEmptyCompletion(assistantText) && (exitCode === 0 || exitCode == null)) {
621
+ return 2;
622
+ }
623
+ return exitCode;
624
+ }
601
625
  async function fetchTeamChatTargets(team) {
602
626
  const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
603
627
  let agents = [
@@ -1101,6 +1125,12 @@ function parseDiffStat(result) {
1101
1125
  }
1102
1126
  return {};
1103
1127
  }
1128
+ var THINKING_PART_MAX_CHARS = 64e3;
1129
+ function clipThinkingForStore(text, max = THINKING_PART_MAX_CHARS) {
1130
+ if (text.length <= max) return text;
1131
+ const marker = "\u2026(earlier thinking trimmed)\n";
1132
+ return marker + text.slice(text.length - Math.max(1, max - marker.length));
1133
+ }
1104
1134
  function withPartTimes(next, prev) {
1105
1135
  const now = Date.now();
1106
1136
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
@@ -1143,7 +1173,7 @@ function applyAgentEvent(parts, event) {
1143
1173
  next[i] = withPartTimes(
1144
1174
  {
1145
1175
  type: "thinking",
1146
- text: data,
1176
+ text: clipThinkingForStore(data),
1147
1177
  ...event.parentId ? { parentId: event.parentId } : {}
1148
1178
  },
1149
1179
  prev
@@ -1154,7 +1184,7 @@ function applyAgentEvent(parts, event) {
1154
1184
  next.push(
1155
1185
  withPartTimes({
1156
1186
  type: "thinking",
1157
- text: data,
1187
+ text: clipThinkingForStore(data),
1158
1188
  ...event.parentId ? { parentId: event.parentId } : {}
1159
1189
  })
1160
1190
  );
@@ -1165,7 +1195,7 @@ function applyAgentEvent(parts, event) {
1165
1195
  next[next.length - 1] = withPartTimes(
1166
1196
  {
1167
1197
  type: "thinking",
1168
- text: last.text + data,
1198
+ text: clipThinkingForStore(last.text + data),
1169
1199
  ...event.parentId ? { parentId: event.parentId } : {}
1170
1200
  },
1171
1201
  last
@@ -4341,6 +4371,7 @@ export {
4341
4371
  applySystemCaEnv,
4342
4372
  trustSystemCertificates,
4343
4373
  pushTurnStderr,
4374
+ clipToolResultForStore,
4344
4375
  looksLikeV8Oom,
4345
4376
  summarizeTurnStderr,
4346
4377
  looksLikeInvalidAgentSession,
@@ -4357,6 +4388,7 @@ export {
4357
4388
  encodeBrightsyTarget,
4358
4389
  decodeBrightsyTarget,
4359
4390
  parseBrightsyCliLine,
4391
+ adjustBrightsyTurnExit,
4360
4392
  listBrightsyChatTargets,
4361
4393
  brightsyAdapter,
4362
4394
  toolDescription,
package/dist/index.cjs CHANGED
@@ -3825,6 +3825,14 @@ var init_worktree_labels = __esm({
3825
3825
  });
3826
3826
 
3827
3827
  // src/store/setup-log.ts
3828
+ function appendSetupOutput(prev, line, max = MAX_SETUP_LOG_CHARS) {
3829
+ const next = prev ? `${prev}
3830
+ ${line}` : line;
3831
+ if (next.length <= max) return next;
3832
+ const cut = next.slice(next.length - max);
3833
+ const nl = cut.indexOf("\n");
3834
+ return nl >= 0 && nl < cut.length - 1 ? cut.slice(nl + 1) : cut;
3835
+ }
3828
3836
  function setupLogPath(threadId) {
3829
3837
  return (0, import_node_path11.join)(threadsDir(), `${threadId}.setup.log.json`);
3830
3838
  }
@@ -3910,8 +3918,7 @@ function appendSetupLog(threadId, line) {
3910
3918
  const current = memory.get(threadId) ?? readSetupLog(threadId);
3911
3919
  const snap = {
3912
3920
  ...current,
3913
- output: current.output ? `${current.output}
3914
- ${line}` : line,
3921
+ output: appendSetupOutput(current.output, line),
3915
3922
  running: true
3916
3923
  };
3917
3924
  memory.set(threadId, snap);
@@ -3930,7 +3937,7 @@ function finishSetupLog(threadId, exitCode, source) {
3930
3937
  persistNow(threadId);
3931
3938
  return clone(snap);
3932
3939
  }
3933
- var import_node_crypto4, import_node_fs10, import_node_path11, EMPTY, memory, persistTimers;
3940
+ var import_node_crypto4, import_node_fs10, import_node_path11, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers;
3934
3941
  var init_setup_log = __esm({
3935
3942
  "src/store/setup-log.ts"() {
3936
3943
  "use strict";
@@ -3945,6 +3952,7 @@ var init_setup_log = __esm({
3945
3952
  exitCode: null,
3946
3953
  source: null
3947
3954
  };
3955
+ MAX_SETUP_LOG_CHARS = 256e3;
3948
3956
  memory = /* @__PURE__ */ new Map();
3949
3957
  persistTimers = /* @__PURE__ */ new Map();
3950
3958
  }
@@ -8856,11 +8864,20 @@ function looksLikeInvalidAgentSession(text7) {
8856
8864
  if (!lower) return false;
8857
8865
  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) || /\brun\b.{0,80}\bnot found for agent\b/.test(lower);
8858
8866
  }
8867
+ function looksLikeCursorHttp2StreamClose(text7) {
8868
+ return /nghttp2/i.test(text7.trim());
8869
+ }
8870
+ function looksLikeBrightsyEmptyCompletion(text7) {
8871
+ const core = text7.trim().replace(/^exit\s*\d+:\s*/i, "").replace(/^error:\s*/i, "").trim();
8872
+ return /^i did not receive a valid model response\. please try again\.$/i.test(core);
8873
+ }
8859
8874
  function looksLikeRetryableRunnerCrash(text7) {
8860
8875
  if (looksLikeAgentFailureMessage(text7)) return false;
8861
8876
  if (looksLikeInvalidAgentSession(text7)) return false;
8862
8877
  if (looksLikeV8Oom(text7)) return false;
8863
8878
  if (looksLikeHugeToolResultDump(text7)) return true;
8879
+ if (looksLikeCursorHttp2StreamClose(text7)) return true;
8880
+ if (looksLikeBrightsyEmptyCompletion(text7)) return true;
8864
8881
  const lower = text7.trim().toLowerCase();
8865
8882
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
8866
8883
  if (!lower) return true;
@@ -8933,9 +8950,12 @@ function humanizeAgentFailDetail(detail) {
8933
8950
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
8934
8951
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
8935
8952
  }
8936
- if (/connection stalled/.test(lower)) {
8953
+ if (/connection stalled/.test(lower) || looksLikeCursorHttp2StreamClose(raw)) {
8937
8954
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
8938
8955
  }
8956
+ if (looksLikeBrightsyEmptyCompletion(raw)) {
8957
+ return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Brightsy returned an empty model completion).`;
8958
+ }
8939
8959
  if (/network request failed|cursor startup failed:.+\(retryable\)/.test(lower)) {
8940
8960
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (a transient Cursor SDK network error).`;
8941
8961
  }
@@ -9677,6 +9697,12 @@ function parseBrightsyCliLine(line) {
9677
9697
  try {
9678
9698
  const obj = JSON.parse(trimmed);
9679
9699
  if (obj.type === "text" && typeof obj.text === "string") {
9700
+ if (looksLikeBrightsyEmptyCompletion(obj.text)) {
9701
+ return [
9702
+ { type: "stderr", data: obj.text },
9703
+ { type: "stdout", data: `Error: ${obj.text}` }
9704
+ ];
9705
+ }
9680
9706
  return { type: "stdout", data: obj.text };
9681
9707
  }
9682
9708
  if (obj.type === "thinking" && typeof obj.text === "string") {
@@ -9720,7 +9746,7 @@ function parseBrightsyCliLine(line) {
9720
9746
  if (trimmed.startsWith("{") && /"type"\s*:\s*"(tool_use|tool_result|tool|text|thinking|usage|done|error)"/.test(trimmed)) {
9721
9747
  return null;
9722
9748
  }
9723
- if (/error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
9749
+ if (looksLikeBrightsyEmptyCompletion(trimmed) || /error|failed|unauthorized|quota|limit|not logged in/i.test(trimmed)) {
9724
9750
  return [
9725
9751
  { type: "stderr", data: trimmed },
9726
9752
  { type: "stdout", data: `Error: ${trimmed}` }
@@ -9729,6 +9755,12 @@ function parseBrightsyCliLine(line) {
9729
9755
  return { type: "stdout", data: line };
9730
9756
  }
9731
9757
  }
9758
+ function adjustBrightsyTurnExit(exitCode, assistantText) {
9759
+ if (looksLikeBrightsyEmptyCompletion(assistantText) && (exitCode === 0 || exitCode == null)) {
9760
+ return 2;
9761
+ }
9762
+ return exitCode;
9763
+ }
9732
9764
  async function fetchTeamChatTargets(team) {
9733
9765
  const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
9734
9766
  let agents = [
@@ -10031,11 +10063,17 @@ function clipChatLine(value, max = CHAT_DETAIL_MAX) {
10031
10063
  if (line.length <= max) return line;
10032
10064
  return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
10033
10065
  }
10066
+ function rootedPathWithSpaces(trimmed) {
10067
+ const [head = "", ...rest] = trimmed.split(/\s+/);
10068
+ if (SHELL_BIN_DIR.test(head)) return false;
10069
+ return rest.every((tok) => !/^[-/~$]/.test(tok) && !tok.includes("="));
10070
+ }
10034
10071
  function looksLikeFilePath(value) {
10035
10072
  const trimmed = value.trim();
10036
- if (!trimmed || /[\s;|&<>]/.test(trimmed)) return false;
10037
- if (trimmed.startsWith("/") || trimmed.startsWith("~/")) return true;
10038
- if (/^[A-Za-z]:[\\/]/.test(trimmed)) return true;
10073
+ if (!trimmed || /[\r\n;|&<>]/.test(trimmed)) return false;
10074
+ const rooted = trimmed.startsWith("/") || trimmed.startsWith("~/") || /^[A-Za-z]:[\\/]/.test(trimmed);
10075
+ if (/\s/.test(trimmed)) return rooted && rootedPathWithSpaces(trimmed);
10076
+ if (rooted) return true;
10039
10077
  return trimmed.includes("/") || trimmed.includes("\\");
10040
10078
  }
10041
10079
  function stripWorktreePrefix(path2, worktreePath) {
@@ -10360,6 +10398,11 @@ function parseDiffStat(result) {
10360
10398
  }
10361
10399
  return {};
10362
10400
  }
10401
+ function clipThinkingForStore(text7, max = THINKING_PART_MAX_CHARS) {
10402
+ if (text7.length <= max) return text7;
10403
+ const marker = "\u2026(earlier thinking trimmed)\n";
10404
+ return marker + text7.slice(text7.length - Math.max(1, max - marker.length));
10405
+ }
10363
10406
  function withPartTimes(next, prev) {
10364
10407
  const now = Date.now();
10365
10408
  const startedAt = prev && typeof prev.startedAt === "number" ? prev.startedAt : now;
@@ -10402,7 +10445,7 @@ function applyAgentEvent(parts, event) {
10402
10445
  next[i] = withPartTimes(
10403
10446
  {
10404
10447
  type: "thinking",
10405
- text: data,
10448
+ text: clipThinkingForStore(data),
10406
10449
  ...event.parentId ? { parentId: event.parentId } : {}
10407
10450
  },
10408
10451
  prev
@@ -10413,7 +10456,7 @@ function applyAgentEvent(parts, event) {
10413
10456
  next.push(
10414
10457
  withPartTimes({
10415
10458
  type: "thinking",
10416
- text: data,
10459
+ text: clipThinkingForStore(data),
10417
10460
  ...event.parentId ? { parentId: event.parentId } : {}
10418
10461
  })
10419
10462
  );
@@ -10424,7 +10467,7 @@ function applyAgentEvent(parts, event) {
10424
10467
  next[next.length - 1] = withPartTimes(
10425
10468
  {
10426
10469
  type: "thinking",
10427
- text: last.text + data,
10470
+ text: clipThinkingForStore(last.text + data),
10428
10471
  ...event.parentId ? { parentId: event.parentId } : {}
10429
10472
  },
10430
10473
  last
@@ -10586,12 +10629,14 @@ function normalizeParseResult(parsed) {
10586
10629
  if (!parsed) return [];
10587
10630
  return Array.isArray(parsed) ? parsed : [parsed];
10588
10631
  }
10589
- var CHAT_DETAIL_MAX;
10632
+ var CHAT_DETAIL_MAX, SHELL_BIN_DIR, THINKING_PART_MAX_CHARS;
10590
10633
  var init_message_parts = __esm({
10591
10634
  "src/agents/message-parts.ts"() {
10592
10635
  "use strict";
10593
10636
  init_error_detail();
10594
10637
  CHAT_DETAIL_MAX = 72;
10638
+ SHELL_BIN_DIR = /^(?:\/usr\/local\/bin|\/usr\/bin|\/bin|\/opt\/homebrew\/bin|\/sbin|\/usr\/sbin)\//;
10639
+ THINKING_PART_MAX_CHARS = 64e3;
10595
10640
  }
10596
10641
  });
10597
10642
 
@@ -14194,11 +14239,11 @@ async function spawnAgentTurn(thread, input, onEvent) {
14194
14239
  consume(child.stderr, "stderr");
14195
14240
  const done = child.then((result) => {
14196
14241
  outbound.flush();
14197
- const exitCode = result.exitCode ?? null;
14198
- onEvent({ type: "exit", data: exitCode });
14199
14242
  const finalized = finalizeParts(parts);
14200
14243
  const rawText = assistantText.trim() || partsToAssistantText(finalized);
14201
14244
  const text7 = thread.agent === "brightsy" ? stripBrightsyNdjsonNoise(rawText) : rawText;
14245
+ const exitCode = thread.agent === "brightsy" ? adjustBrightsyTurnExit(result.exitCode ?? null, text7) : result.exitCode ?? null;
14246
+ onEvent({ type: "exit", data: exitCode });
14202
14247
  return { exitCode, sessionId, assistantText: text7, parts: finalized, usage };
14203
14248
  });
14204
14249
  return {
@@ -14569,7 +14614,7 @@ function formatToolPart(t, detail) {
14569
14614
  if (t.input && Object.keys(t.input).length > 0) {
14570
14615
  lines.push("Input:");
14571
14616
  lines.push("```json");
14572
- lines.push(JSON.stringify(t.input, null, 2));
14617
+ lines.push(clipToolResultForStore(JSON.stringify(t.input, null, 2)) ?? "");
14573
14618
  lines.push("```");
14574
14619
  } else if (t.detail) {
14575
14620
  lines.push(`Detail: ${t.detail}`);
@@ -14617,19 +14662,7 @@ ${m.text}`);
14617
14662
  }
14618
14663
  return bits.join("\n");
14619
14664
  }
14620
- function buildSessionSeed(messages, opts) {
14621
- if (messages.length === 0) return null;
14622
- const tools = opts?.tools ?? "full";
14623
- const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
14624
- const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
14625
- const olderTools = tools === "none" ? "none" : "summary";
14626
- const fullFrom = Math.max(0, messages.length - fullCount);
14627
- const blocks = messages.map(
14628
- (m, i) => formatMessageBlock(m, {
14629
- tools: i >= fullFrom ? tools : olderTools,
14630
- thinking: false
14631
- })
14632
- );
14665
+ function budgetSeedBlocks(messages, blocks, maxChars) {
14633
14666
  const keep = new Array(blocks.length).fill(false);
14634
14667
  let used = 0;
14635
14668
  for (let i = 0; i < blocks.length; i++) {
@@ -14646,20 +14679,34 @@ function buildSessionSeed(messages, opts) {
14646
14679
  used = next;
14647
14680
  }
14648
14681
  const dropped = keep.filter((k) => !k).length;
14682
+ const marker = `_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`;
14649
14683
  const kept = [];
14650
14684
  let markerPlaced = false;
14651
14685
  for (let i = 0; i < blocks.length; i++) {
14652
14686
  if (!keep[i]) continue;
14653
14687
  if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
14654
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
14688
+ kept.push(marker);
14655
14689
  markerPlaced = true;
14656
14690
  }
14657
14691
  kept.push(blocks[i]);
14658
14692
  }
14659
- if (dropped > 0 && !markerPlaced) {
14660
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
14661
- }
14662
- const body = kept.join("\n\n");
14693
+ if (dropped > 0 && !markerPlaced) kept.push(marker);
14694
+ return kept.join("\n\n");
14695
+ }
14696
+ function buildSessionSeed(messages, opts) {
14697
+ if (messages.length === 0) return null;
14698
+ const tools = opts?.tools ?? "full";
14699
+ const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
14700
+ const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
14701
+ const olderTools = tools === "none" ? "none" : "summary";
14702
+ const fullFrom = Math.max(0, messages.length - fullCount);
14703
+ const blocks = messages.map(
14704
+ (m, i) => formatMessageBlock(m, {
14705
+ tools: i >= fullFrom ? tools : olderTools,
14706
+ thinking: false
14707
+ })
14708
+ );
14709
+ const body = budgetSeedBlocks(messages, blocks, maxChars);
14663
14710
  if (!body.trim()) return null;
14664
14711
  return [
14665
14712
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -14714,10 +14761,12 @@ function messagesSinceLastBrightsyContextSummary(messages) {
14714
14761
  if (!match) return messages;
14715
14762
  return messages.slice(match.index + 1);
14716
14763
  }
14717
- function buildBrightsySessionSeed(messages) {
14764
+ function buildBrightsySessionSeed(messages, opts) {
14718
14765
  const match = findLastBrightsyContextSummary(messages);
14719
14766
  const tail = match ? messages.slice(match.index + 1) : messages;
14720
- const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
14767
+ const budget = Math.max(1e3, (opts?.maxChars ?? SEED_MAX_CHARS) - (match?.text.length ?? 0));
14768
+ const tailBlocks = tail.map((m) => formatMessageBlock(m, { tools: "none", thinking: false }));
14769
+ const body = budgetSeedBlocks(tail, tailBlocks, budget);
14721
14770
  if (!match && !body.trim()) return null;
14722
14771
  const blocks = [
14723
14772
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -14788,6 +14837,7 @@ var CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAG
14788
14837
  var init_context_compact = __esm({
14789
14838
  "src/composer/context-compact.ts"() {
14790
14839
  "use strict";
14840
+ init_error_detail();
14791
14841
  init_usage();
14792
14842
  init_context_estimate();
14793
14843
  init_summarize();
@@ -14838,6 +14888,10 @@ function pickRichestSetupLog(snaps) {
14838
14888
  }
14839
14889
  return best;
14840
14890
  }
14891
+ function resolveWorktreeSetupLog(shared, legacyChatLogs) {
14892
+ if (shared.output || shared.running || shared.exitCode != null) return shared;
14893
+ return pickRichestSetupLog(legacyChatLogs);
14894
+ }
14841
14895
  function mergeWorktreeActiveRuns(threads) {
14842
14896
  const byName = /* @__PURE__ */ new Map();
14843
14897
  let devPort = null;
@@ -21683,6 +21737,7 @@ var init_orchestrator = __esm({
21683
21737
  return true;
21684
21738
  });
21685
21739
  if (!promoted) return this.requireThread(thread.id);
21740
+ if (!thisProcessShouldDrainAgentQueues()) return this.requireThread(thread.id);
21686
21741
  const current = this.requireThread(thread.id);
21687
21742
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
21688
21743
  const livePid = current.agentPid;
@@ -22423,10 +22478,10 @@ var init_orchestrator = __esm({
22423
22478
  thread.id,
22424
22479
  ...threadsSharingWorktree(thread.worktreePath).map((t) => t.id)
22425
22480
  ];
22426
- const snap = pickRichestSetupLog([
22481
+ const snap = resolveWorktreeSetupLog(
22427
22482
  readSetupLog(setupLogKeyForWorktree(thread.worktreePath)),
22428
- ...[...new Set(siblingIds)].map((id) => readSetupLog(id))
22429
- ]) ?? readSetupLog(thread.id);
22483
+ [...new Set(siblingIds)].map((id) => readSetupLog(id))
22484
+ ) ?? readSetupLog(thread.id);
22430
22485
  if (snap.running && !this.hasWorktreeSetupProcess(thread.worktreePath)) {
22431
22486
  return { ...snap, running: false };
22432
22487
  }
@@ -23481,6 +23536,7 @@ __export(index_exports, {
23481
23536
  SlackOAuthCancelledError: () => SlackOAuthCancelledError,
23482
23537
  SlackRelayHub: () => SlackRelayHub,
23483
23538
  THINKING_EFFORTS: () => THINKING_EFFORTS,
23539
+ THINKING_PART_MAX_CHARS: () => THINKING_PART_MAX_CHARS,
23484
23540
  WORKTREE_ABLETIME_MCP_TOOLS: () => WORKTREE_ABLETIME_MCP_TOOLS,
23485
23541
  WORKTREE_GITHUB_MCP_TOOLS: () => WORKTREE_GITHUB_MCP_TOOLS,
23486
23542
  WORKTREE_LINEAR_MCP_TOOLS: () => WORKTREE_LINEAR_MCP_TOOLS,
@@ -23566,6 +23622,7 @@ __export(index_exports, {
23566
23622
  cleanupOrphanWorktrees: () => cleanupOrphanWorktrees,
23567
23623
  clearBoardPins: () => clearBoardPins,
23568
23624
  clearHomeBoardCache: () => clearHomeBoardCache,
23625
+ clipThinkingForStore: () => clipThinkingForStore,
23569
23626
  cloneRepoIntoSideboard: () => cloneRepoIntoSideboard,
23570
23627
  codeRefRangeLabel: () => codeRefRangeLabel,
23571
23628
  codexAdapter: () => codexAdapter,
@@ -29159,7 +29216,7 @@ async function startMcpServer() {
29159
29216
  );
29160
29217
  server.tool(
29161
29218
  "send_to_thread",
29162
- 'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: interrupt and start now, skip the inbox). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
29219
+ 'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: front of the queue, skips the inbox; while the desktop board is running it starts as soon as the in-flight turn yields). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
29163
29220
  {
29164
29221
  ref: import_zod9.z.string(),
29165
29222
  prompt: import_zod9.z.string(),
@@ -32097,6 +32154,7 @@ init_outbound_watch();
32097
32154
  SlackOAuthCancelledError,
32098
32155
  SlackRelayHub,
32099
32156
  THINKING_EFFORTS,
32157
+ THINKING_PART_MAX_CHARS,
32100
32158
  WORKTREE_ABLETIME_MCP_TOOLS,
32101
32159
  WORKTREE_GITHUB_MCP_TOOLS,
32102
32160
  WORKTREE_LINEAR_MCP_TOOLS,
@@ -32182,6 +32240,7 @@ init_outbound_watch();
32182
32240
  cleanupOrphanWorktrees,
32183
32241
  clearBoardPins,
32184
32242
  clearHomeBoardCache,
32243
+ clipThinkingForStore,
32185
32244
  cloneRepoIntoSideboard,
32186
32245
  codeRefRangeLabel,
32187
32246
  codexAdapter,