@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.
@@ -220,6 +220,53 @@ function sanitizeCursorStoreSegment(threadId) {
220
220
  return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
221
221
  }
222
222
 
223
+ // src/agents/error-detail.ts
224
+ function formatUnknownDetail(err) {
225
+ if (err == null) return "";
226
+ if (typeof err === "string") return err.trim();
227
+ if (err instanceof Error) {
228
+ const base = err.message.trim() || err.name;
229
+ const code = "code" in err && typeof err.code === "string" ? err.code.trim() : "";
230
+ return code && !base.includes(code) ? `${base} (${code})` : base;
231
+ }
232
+ if (typeof err === "object") {
233
+ const o = err;
234
+ const nested = o.error != null && typeof o.error === "object" ? formatUnknownDetail(o.error) : "";
235
+ const message = typeof o.message === "string" ? o.message.trim() : typeof o.error === "string" ? o.error.trim() : typeof o.result === "string" ? o.result.trim() : nested;
236
+ const code = typeof o.code === "string" ? o.code.trim() : "";
237
+ if (message) return code && !message.includes(code) ? `${message} (${code})` : message;
238
+ try {
239
+ const json = JSON.stringify(err);
240
+ if (json && json !== "{}" && json !== "null") return json;
241
+ } catch {
242
+ }
243
+ }
244
+ const fallback = String(err);
245
+ return fallback === "[object Object]" ? "" : fallback;
246
+ }
247
+ function extractJsonErrorMessage(obj) {
248
+ const nested = obj.error != null && typeof obj.error === "object" ? obj.error : null;
249
+ const candidates = [
250
+ typeof obj.message === "string" ? obj.message : null,
251
+ typeof obj.error === "string" ? obj.error : null,
252
+ nested && typeof nested.message === "string" ? nested.message : null,
253
+ typeof obj.result === "string" ? obj.result : null,
254
+ typeof obj.detail === "string" ? obj.detail : null
255
+ ];
256
+ for (const c of candidates) {
257
+ const t = c?.trim();
258
+ if (t) return t;
259
+ }
260
+ if (Array.isArray(obj.errors)) {
261
+ const parts = obj.errors.map((e) => formatUnknownDetail(e)).map((s) => s.trim()).filter(Boolean);
262
+ if (parts.length) return parts.join("; ");
263
+ }
264
+ return null;
265
+ }
266
+ function looksLikeCursorHttp2StreamClose(text) {
267
+ return /nghttp2/i.test(text.trim());
268
+ }
269
+
223
270
  // src/agents/cursor-session.ts
224
271
  function cursorErrorMessage(err) {
225
272
  if (err instanceof Error) return err.message.trim();
@@ -251,7 +298,8 @@ function isRetryableCursorTransportError(err) {
251
298
  if (err && typeof err === "object" && "isRetryable" in err && err.isRetryable === true) {
252
299
  return true;
253
300
  }
254
- return /network request failed/i.test(cursorErrorMessage(err));
301
+ const message = cursorErrorMessage(err);
302
+ return /network request failed/i.test(message) || looksLikeCursorHttp2StreamClose(message);
255
303
  }
256
304
  function looksLikeNonRetryableCursorFailure(message) {
257
305
  const lower = message.toLowerCase();
@@ -324,50 +372,6 @@ async function* iterateUntilIdle(iterable, idleMs, onIdle, activity) {
324
372
  }
325
373
  }
326
374
 
327
- // src/agents/error-detail.ts
328
- function formatUnknownDetail(err) {
329
- if (err == null) return "";
330
- if (typeof err === "string") return err.trim();
331
- if (err instanceof Error) {
332
- const base = err.message.trim() || err.name;
333
- const code = "code" in err && typeof err.code === "string" ? err.code.trim() : "";
334
- return code && !base.includes(code) ? `${base} (${code})` : base;
335
- }
336
- if (typeof err === "object") {
337
- const o = err;
338
- const nested = o.error != null && typeof o.error === "object" ? formatUnknownDetail(o.error) : "";
339
- const message = typeof o.message === "string" ? o.message.trim() : typeof o.error === "string" ? o.error.trim() : typeof o.result === "string" ? o.result.trim() : nested;
340
- const code = typeof o.code === "string" ? o.code.trim() : "";
341
- if (message) return code && !message.includes(code) ? `${message} (${code})` : message;
342
- try {
343
- const json = JSON.stringify(err);
344
- if (json && json !== "{}" && json !== "null") return json;
345
- } catch {
346
- }
347
- }
348
- const fallback = String(err);
349
- return fallback === "[object Object]" ? "" : fallback;
350
- }
351
- function extractJsonErrorMessage(obj) {
352
- const nested = obj.error != null && typeof obj.error === "object" ? obj.error : null;
353
- const candidates = [
354
- typeof obj.message === "string" ? obj.message : null,
355
- typeof obj.error === "string" ? obj.error : null,
356
- nested && typeof nested.message === "string" ? nested.message : null,
357
- typeof obj.result === "string" ? obj.result : null,
358
- typeof obj.detail === "string" ? obj.detail : null
359
- ];
360
- for (const c of candidates) {
361
- const t = c?.trim();
362
- if (t) return t;
363
- }
364
- if (Array.isArray(obj.errors)) {
365
- const parts = obj.errors.map((e) => formatUnknownDetail(e)).map((s) => s.trim()).filter(Boolean);
366
- if (parts.length) return parts.join("; ");
367
- }
368
- return null;
369
- }
370
-
371
375
  // src/agents/cursor-events.ts
372
376
  function usageFromCursor(usage) {
373
377
  if (!usage) return null;
@@ -11,8 +11,9 @@ import {
11
11
  cursorSdkMessageToEvents,
12
12
  ensureCursorRipgrepPath,
13
13
  fetchCursorTurnCostUsd,
14
- formatUnknownDetail
15
- } from "../chunk-NLHFAMC2.js";
14
+ formatUnknownDetail,
15
+ looksLikeCursorHttp2StreamClose
16
+ } from "../chunk-CQ5R3VPP.js";
16
17
  import {
17
18
  dropNestedElectronEnvFromProcess
18
19
  } from "../chunk-4TR3HZFT.js";
@@ -55,7 +56,8 @@ function isRetryableCursorTransportError(err) {
55
56
  if (err && typeof err === "object" && "isRetryable" in err && err.isRetryable === true) {
56
57
  return true;
57
58
  }
58
- return /network request failed/i.test(cursorErrorMessage(err));
59
+ const message = cursorErrorMessage(err);
60
+ return /network request failed/i.test(message) || looksLikeCursorHttp2StreamClose(message);
59
61
  }
60
62
  function looksLikeNonRetryableCursorFailure(message) {
61
63
  const lower = message.toLowerCase();
@@ -38,7 +38,7 @@ import {
38
38
  resolveQuotaFallbackAgent,
39
39
  turnCostUsdFromCursorUsage,
40
40
  whichOnPath
41
- } from "./chunk-5DY2QWVN.js";
41
+ } from "./chunk-SYXSSU7G.js";
42
42
  import "./chunk-6YTI2HBG.js";
43
43
  import "./chunk-3OHR73VK.js";
44
44
  import "./chunk-Y4MIXGPA.js";
@@ -32,7 +32,7 @@ import {
32
32
  resolveLoginCommand,
33
33
  resolveQuotaFallbackAgent,
34
34
  whichOnPath
35
- } from "./chunk-NWIBA5CP.js";
35
+ } from "./chunk-EA67VQM2.js";
36
36
  import "./chunk-HZTHWU6A.js";
37
37
  import "./chunk-S4QCBBXS.js";
38
38
  import "./chunk-6K64FJDD.js";
@@ -45,7 +45,7 @@ import {
45
45
  parseCursorRunnerLine,
46
46
  preferredCursorCostCents,
47
47
  turnCostUsdFromCursorUsage
48
- } from "./chunk-NLHFAMC2.js";
48
+ } from "./chunk-CQ5R3VPP.js";
49
49
  import {
50
50
  ORCHESTRATOR_AGENT_KINDS,
51
51
  assertOrchestratorCapableAgent,
@@ -5,6 +5,7 @@ import {
5
5
  } from "./chunk-DJU54RYW.js";
6
6
  import {
7
7
  PLAN_MODE_INSTRUCTION,
8
+ adjustBrightsyTurnExit,
8
9
  allAdapters,
9
10
  applyAgentEvent,
10
11
  applyTurnUsage,
@@ -24,7 +25,7 @@ import {
24
25
  stripBrightsyNdjsonNoise,
25
26
  sumUsageList,
26
27
  toolDescription
27
- } from "./chunk-NWIBA5CP.js";
28
+ } from "./chunk-EA67VQM2.js";
28
29
  import {
29
30
  SLACK_REPLY_FORMATTING,
30
31
  addWorkspace,
@@ -115,6 +116,7 @@ import {
115
116
  } from "./chunk-AXQ4ZWHK.js";
116
117
  import {
117
118
  applyAgentRunnerHeapEnv,
119
+ clipToolResultForStore,
118
120
  fallbackTurnFailDetail,
119
121
  formatAgentErrorContinuePrompt,
120
122
  formatTurnExitError,
@@ -127,7 +129,7 @@ import {
127
129
  shouldRetryFailedAgentTurn,
128
130
  summarizeTurnStderr,
129
131
  turnFailChatText
130
- } from "./chunk-NLHFAMC2.js";
132
+ } from "./chunk-CQ5R3VPP.js";
131
133
  import {
132
134
  assertOrchestratorCapableAgent,
133
135
  childEnvWithAppSettings,
@@ -471,7 +473,7 @@ async function continueSourceThread(threadId, prompt) {
471
473
  await continueOnReply(threadId, prompt);
472
474
  return;
473
475
  }
474
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-CT7VSL7B.js");
476
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6ZNKCPNL.js");
475
477
  await getOrchestrator2().send(threadId, prompt);
476
478
  } catch {
477
479
  }
@@ -903,11 +905,11 @@ async function spawnAgentTurn(thread, input, onEvent) {
903
905
  consume(child.stderr, "stderr");
904
906
  const done = child.then((result) => {
905
907
  outbound.flush();
906
- const exitCode = result.exitCode ?? null;
907
- onEvent({ type: "exit", data: exitCode });
908
908
  const finalized = finalizeParts(parts);
909
909
  const rawText = assistantText.trim() || partsToAssistantText(finalized);
910
910
  const text = thread.agent === "brightsy" ? stripBrightsyNdjsonNoise(rawText) : rawText;
911
+ const exitCode = thread.agent === "brightsy" ? adjustBrightsyTurnExit(result.exitCode ?? null, text) : result.exitCode ?? null;
912
+ onEvent({ type: "exit", data: exitCode });
911
913
  return { exitCode, sessionId, assistantText: text, parts: finalized, usage };
912
914
  });
913
915
  return {
@@ -1256,7 +1258,7 @@ function formatToolPart(t, detail) {
1256
1258
  if (t.input && Object.keys(t.input).length > 0) {
1257
1259
  lines.push("Input:");
1258
1260
  lines.push("```json");
1259
- lines.push(JSON.stringify(t.input, null, 2));
1261
+ lines.push(clipToolResultForStore(JSON.stringify(t.input, null, 2)) ?? "");
1260
1262
  lines.push("```");
1261
1263
  } else if (t.detail) {
1262
1264
  lines.push(`Detail: ${t.detail}`);
@@ -1306,19 +1308,7 @@ ${m.text}`);
1306
1308
  }
1307
1309
  var SEED_MAX_CHARS = 6e4;
1308
1310
  var SEED_FULL_TOOL_MESSAGES = 6;
1309
- function buildSessionSeed(messages, opts) {
1310
- if (messages.length === 0) return null;
1311
- const tools = opts?.tools ?? "full";
1312
- const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
1313
- const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
1314
- const olderTools = tools === "none" ? "none" : "summary";
1315
- const fullFrom = Math.max(0, messages.length - fullCount);
1316
- const blocks = messages.map(
1317
- (m, i) => formatMessageBlock(m, {
1318
- tools: i >= fullFrom ? tools : olderTools,
1319
- thinking: false
1320
- })
1321
- );
1311
+ function budgetSeedBlocks(messages, blocks, maxChars) {
1322
1312
  const keep = new Array(blocks.length).fill(false);
1323
1313
  let used = 0;
1324
1314
  for (let i = 0; i < blocks.length; i++) {
@@ -1335,20 +1325,34 @@ function buildSessionSeed(messages, opts) {
1335
1325
  used = next;
1336
1326
  }
1337
1327
  const dropped = keep.filter((k) => !k).length;
1328
+ const marker = `_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`;
1338
1329
  const kept = [];
1339
1330
  let markerPlaced = false;
1340
1331
  for (let i = 0; i < blocks.length; i++) {
1341
1332
  if (!keep[i]) continue;
1342
1333
  if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
1343
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1334
+ kept.push(marker);
1344
1335
  markerPlaced = true;
1345
1336
  }
1346
1337
  kept.push(blocks[i]);
1347
1338
  }
1348
- if (dropped > 0 && !markerPlaced) {
1349
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1350
- }
1351
- const body = kept.join("\n\n");
1339
+ if (dropped > 0 && !markerPlaced) kept.push(marker);
1340
+ return kept.join("\n\n");
1341
+ }
1342
+ function buildSessionSeed(messages, opts) {
1343
+ if (messages.length === 0) return null;
1344
+ const tools = opts?.tools ?? "full";
1345
+ const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
1346
+ const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
1347
+ const olderTools = tools === "none" ? "none" : "summary";
1348
+ const fullFrom = Math.max(0, messages.length - fullCount);
1349
+ const blocks = messages.map(
1350
+ (m, i) => formatMessageBlock(m, {
1351
+ tools: i >= fullFrom ? tools : olderTools,
1352
+ thinking: false
1353
+ })
1354
+ );
1355
+ const body = budgetSeedBlocks(messages, blocks, maxChars);
1352
1356
  if (!body.trim()) return null;
1353
1357
  return [
1354
1358
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -1404,10 +1408,12 @@ function messagesSinceLastBrightsyContextSummary(messages) {
1404
1408
  if (!match) return messages;
1405
1409
  return messages.slice(match.index + 1);
1406
1410
  }
1407
- function buildBrightsySessionSeed(messages) {
1411
+ function buildBrightsySessionSeed(messages, opts) {
1408
1412
  const match = findLastBrightsyContextSummary(messages);
1409
1413
  const tail = match ? messages.slice(match.index + 1) : messages;
1410
- const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
1414
+ const budget = Math.max(1e3, (opts?.maxChars ?? SEED_MAX_CHARS) - (match?.text.length ?? 0));
1415
+ const tailBlocks = tail.map((m) => formatMessageBlock(m, { tools: "none", thinking: false }));
1416
+ const body = budgetSeedBlocks(tail, tailBlocks, budget);
1411
1417
  if (!match && !body.trim()) return null;
1412
1418
  const blocks = [
1413
1419
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -1510,6 +1516,10 @@ function pickRichestSetupLog(snaps) {
1510
1516
  }
1511
1517
  return best;
1512
1518
  }
1519
+ function resolveWorktreeSetupLog(shared, legacyChatLogs) {
1520
+ if (shared.output || shared.running || shared.exitCode != null) return shared;
1521
+ return pickRichestSetupLog(legacyChatLogs);
1522
+ }
1513
1523
  function mergeWorktreeActiveRuns(threads) {
1514
1524
  const byName = /* @__PURE__ */ new Map();
1515
1525
  let devPort = null;
@@ -2301,6 +2311,15 @@ var EMPTY = {
2301
2311
  exitCode: null,
2302
2312
  source: null
2303
2313
  };
2314
+ var MAX_SETUP_LOG_CHARS = 256e3;
2315
+ function appendSetupOutput(prev, line, max = MAX_SETUP_LOG_CHARS) {
2316
+ const next = prev ? `${prev}
2317
+ ${line}` : line;
2318
+ if (next.length <= max) return next;
2319
+ const cut = next.slice(next.length - max);
2320
+ const nl = cut.indexOf("\n");
2321
+ return nl >= 0 && nl < cut.length - 1 ? cut.slice(nl + 1) : cut;
2322
+ }
2304
2323
  var memory = /* @__PURE__ */ new Map();
2305
2324
  var persistTimers = /* @__PURE__ */ new Map();
2306
2325
  function setupLogPath(threadId) {
@@ -2388,8 +2407,7 @@ function appendSetupLog(threadId, line) {
2388
2407
  const current = memory.get(threadId) ?? readSetupLog(threadId);
2389
2408
  const snap = {
2390
2409
  ...current,
2391
- output: current.output ? `${current.output}
2392
- ${line}` : line,
2410
+ output: appendSetupOutput(current.output, line),
2393
2411
  running: true
2394
2412
  };
2395
2413
  memory.set(threadId, snap);
@@ -3870,7 +3888,7 @@ async function createThread(input, _onSetupLine) {
3870
3888
  return readThread(thread.id) ?? thread;
3871
3889
  }
3872
3890
  async function listLinearIssues(agent, repoPath) {
3873
- const { getAdapter: getAdapter2 } = await import("./agents-2JBVL66D.js");
3891
+ const { getAdapter: getAdapter2 } = await import("./agents-AQQKPD46.js");
3874
3892
  await requireAgent(agent, { requireLinear: true });
3875
3893
  const adapter = getAdapter2(agent);
3876
3894
  if (!adapter.listLinearIssues) {
@@ -6876,7 +6894,7 @@ function formatScheduledPrompt(name, prompt) {
6876
6894
  ${prompt}`;
6877
6895
  }
6878
6896
  async function defaultDeps() {
6879
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-CT7VSL7B.js");
6897
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-6ZNKCPNL.js");
6880
6898
  const orch = getOrchestrator2();
6881
6899
  return {
6882
6900
  findThread: (id) => findThreadByRef(id),
@@ -7571,6 +7589,7 @@ var Orchestrator = class {
7571
7589
  return true;
7572
7590
  });
7573
7591
  if (!promoted) return this.requireThread(thread.id);
7592
+ if (!thisProcessShouldDrainAgentQueues()) return this.requireThread(thread.id);
7574
7593
  const current = this.requireThread(thread.id);
7575
7594
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
7576
7595
  const livePid = current.agentPid;
@@ -8311,10 +8330,10 @@ var Orchestrator = class {
8311
8330
  thread.id,
8312
8331
  ...threadsSharingWorktree(thread.worktreePath).map((t) => t.id)
8313
8332
  ];
8314
- const snap = pickRichestSetupLog([
8333
+ const snap = resolveWorktreeSetupLog(
8315
8334
  readSetupLog(setupLogKeyForWorktree(thread.worktreePath)),
8316
- ...[...new Set(siblingIds)].map((id) => readSetupLog(id))
8317
- ]) ?? readSetupLog(thread.id);
8335
+ [...new Set(siblingIds)].map((id) => readSetupLog(id))
8336
+ ) ?? readSetupLog(thread.id);
8318
8337
  if (snap.running && !this.hasWorktreeSetupProcess(thread.worktreePath)) {
8319
8338
  return { ...snap, running: false };
8320
8339
  }
@@ -207,11 +207,20 @@ function looksLikeInvalidAgentSession(text) {
207
207
  if (!lower) return false;
208
208
  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);
209
209
  }
210
+ function looksLikeCursorHttp2StreamClose(text) {
211
+ return /nghttp2/i.test(text.trim());
212
+ }
213
+ function looksLikeBrightsyEmptyCompletion(text) {
214
+ const core = text.trim().replace(/^exit\s*\d+:\s*/i, "").replace(/^error:\s*/i, "").trim();
215
+ return /^i did not receive a valid model response\. please try again\.$/i.test(core);
216
+ }
210
217
  function looksLikeRetryableRunnerCrash(text) {
211
218
  if (looksLikeAgentFailureMessage(text)) return false;
212
219
  if (looksLikeInvalidAgentSession(text)) return false;
213
220
  if (looksLikeV8Oom(text)) return false;
214
221
  if (looksLikeHugeToolResultDump(text)) return true;
222
+ if (looksLikeCursorHttp2StreamClose(text)) return true;
223
+ if (looksLikeBrightsyEmptyCompletion(text)) return true;
215
224
  const lower = text.trim().toLowerCase();
216
225
  if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
217
226
  if (!lower) return true;
@@ -284,9 +293,12 @@ function humanizeAgentFailDetail(detail) {
284
293
  if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
285
294
  return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
286
295
  }
287
- if (/connection stalled/.test(lower)) {
296
+ if (/connection stalled/.test(lower) || looksLikeCursorHttp2StreamClose(raw)) {
288
297
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
289
298
  }
299
+ if (looksLikeBrightsyEmptyCompletion(raw)) {
300
+ return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Brightsy returned an empty model completion).`;
301
+ }
290
302
  if (/network request failed|cursor startup failed:.+\(retryable\)/.test(lower)) {
291
303
  return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (a transient Cursor SDK network error).`;
292
304
  }
@@ -1098,6 +1110,8 @@ export {
1098
1110
  looksLikeV8Oom,
1099
1111
  summarizeTurnStderr,
1100
1112
  looksLikeInvalidAgentSession,
1113
+ looksLikeCursorHttp2StreamClose,
1114
+ looksLikeBrightsyEmptyCompletion,
1101
1115
  shouldRetryFailedAgentTurn,
1102
1116
  looksLikeAgentFailureMessage,
1103
1117
  fallbackTurnFailDetail,
@@ -5,9 +5,11 @@ import {
5
5
  } from "./chunk-YWI3IBP2.js";
6
6
  import {
7
7
  PLAN_MODE_INSTRUCTION,
8
+ adjustBrightsyTurnExit,
8
9
  applyAgentEvent,
9
10
  applyAgentRunnerHeapEnv,
10
11
  applyTurnUsage,
12
+ clipToolResultForStore,
11
13
  contextTokens,
12
14
  fallbackTurnFailDetail,
13
15
  finalizeParts,
@@ -36,7 +38,7 @@ import {
36
38
  summarizeTurnStderr,
37
39
  toolDescription,
38
40
  turnFailChatText
39
- } from "./chunk-5DY2QWVN.js";
41
+ } from "./chunk-SYXSSU7G.js";
40
42
  import {
41
43
  SLACK_REPLY_FORMATTING,
42
44
  addWorkspace,
@@ -406,7 +408,7 @@ async function continueSourceThread(threadId, prompt) {
406
408
  await continueOnReply(threadId, prompt);
407
409
  return;
408
410
  }
409
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-2FTS55SG.js");
411
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-L2H42HPW.js");
410
412
  await getOrchestrator2().send(threadId, prompt);
411
413
  } catch {
412
414
  }
@@ -897,11 +899,11 @@ async function spawnAgentTurn(thread, input, onEvent) {
897
899
  consume(child.stderr, "stderr");
898
900
  const done = child.then((result) => {
899
901
  outbound.flush();
900
- const exitCode = result.exitCode ?? null;
901
- onEvent({ type: "exit", data: exitCode });
902
902
  const finalized = finalizeParts(parts);
903
903
  const rawText = assistantText.trim() || partsToAssistantText(finalized);
904
904
  const text = thread.agent === "brightsy" ? stripBrightsyNdjsonNoise(rawText) : rawText;
905
+ const exitCode = thread.agent === "brightsy" ? adjustBrightsyTurnExit(result.exitCode ?? null, text) : result.exitCode ?? null;
906
+ onEvent({ type: "exit", data: exitCode });
905
907
  return { exitCode, sessionId, assistantText: text, parts: finalized, usage };
906
908
  });
907
909
  return {
@@ -1230,7 +1232,7 @@ function formatToolPart(t, detail) {
1230
1232
  if (t.input && Object.keys(t.input).length > 0) {
1231
1233
  lines.push("Input:");
1232
1234
  lines.push("```json");
1233
- lines.push(JSON.stringify(t.input, null, 2));
1235
+ lines.push(clipToolResultForStore(JSON.stringify(t.input, null, 2)) ?? "");
1234
1236
  lines.push("```");
1235
1237
  } else if (t.detail) {
1236
1238
  lines.push(`Detail: ${t.detail}`);
@@ -1280,19 +1282,7 @@ ${m.text}`);
1280
1282
  }
1281
1283
  var SEED_MAX_CHARS = 6e4;
1282
1284
  var SEED_FULL_TOOL_MESSAGES = 6;
1283
- function buildSessionSeed(messages, opts) {
1284
- if (messages.length === 0) return null;
1285
- const tools = opts?.tools ?? "full";
1286
- const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
1287
- const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
1288
- const olderTools = tools === "none" ? "none" : "summary";
1289
- const fullFrom = Math.max(0, messages.length - fullCount);
1290
- const blocks = messages.map(
1291
- (m, i) => formatMessageBlock(m, {
1292
- tools: i >= fullFrom ? tools : olderTools,
1293
- thinking: false
1294
- })
1295
- );
1285
+ function budgetSeedBlocks(messages, blocks, maxChars) {
1296
1286
  const keep = new Array(blocks.length).fill(false);
1297
1287
  let used = 0;
1298
1288
  for (let i = 0; i < blocks.length; i++) {
@@ -1309,20 +1299,34 @@ function buildSessionSeed(messages, opts) {
1309
1299
  used = next;
1310
1300
  }
1311
1301
  const dropped = keep.filter((k) => !k).length;
1302
+ const marker = `_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`;
1312
1303
  const kept = [];
1313
1304
  let markerPlaced = false;
1314
1305
  for (let i = 0; i < blocks.length; i++) {
1315
1306
  if (!keep[i]) continue;
1316
1307
  if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
1317
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1308
+ kept.push(marker);
1318
1309
  markerPlaced = true;
1319
1310
  }
1320
1311
  kept.push(blocks[i]);
1321
1312
  }
1322
- if (dropped > 0 && !markerPlaced) {
1323
- kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
1324
- }
1325
- const body = kept.join("\n\n");
1313
+ if (dropped > 0 && !markerPlaced) kept.push(marker);
1314
+ return kept.join("\n\n");
1315
+ }
1316
+ function buildSessionSeed(messages, opts) {
1317
+ if (messages.length === 0) return null;
1318
+ const tools = opts?.tools ?? "full";
1319
+ const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
1320
+ const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
1321
+ const olderTools = tools === "none" ? "none" : "summary";
1322
+ const fullFrom = Math.max(0, messages.length - fullCount);
1323
+ const blocks = messages.map(
1324
+ (m, i) => formatMessageBlock(m, {
1325
+ tools: i >= fullFrom ? tools : olderTools,
1326
+ thinking: false
1327
+ })
1328
+ );
1329
+ const body = budgetSeedBlocks(messages, blocks, maxChars);
1326
1330
  if (!body.trim()) return null;
1327
1331
  return [
1328
1332
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -1373,10 +1377,12 @@ function findLastBrightsyContextSummary(messages) {
1373
1377
  }
1374
1378
  return null;
1375
1379
  }
1376
- function buildBrightsySessionSeed(messages) {
1380
+ function buildBrightsySessionSeed(messages, opts) {
1377
1381
  const match = findLastBrightsyContextSummary(messages);
1378
1382
  const tail = match ? messages.slice(match.index + 1) : messages;
1379
- const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
1383
+ const budget = Math.max(1e3, (opts?.maxChars ?? SEED_MAX_CHARS) - (match?.text.length ?? 0));
1384
+ const tailBlocks = tail.map((m) => formatMessageBlock(m, { tools: "none", thinking: false }));
1385
+ const body = budgetSeedBlocks(tail, tailBlocks, budget);
1380
1386
  if (!match && !body.trim()) return null;
1381
1387
  const blocks = [
1382
1388
  "Sideboard conversation context (restored after compaction or a new session):",
@@ -1479,6 +1485,10 @@ function pickRichestSetupLog(snaps) {
1479
1485
  }
1480
1486
  return best;
1481
1487
  }
1488
+ function resolveWorktreeSetupLog(shared, legacyChatLogs) {
1489
+ if (shared.output || shared.running || shared.exitCode != null) return shared;
1490
+ return pickRichestSetupLog(legacyChatLogs);
1491
+ }
1482
1492
  function mergeWorktreeActiveRuns(threads) {
1483
1493
  const byName = /* @__PURE__ */ new Map();
1484
1494
  let devPort = null;
@@ -2242,6 +2252,15 @@ var EMPTY = {
2242
2252
  exitCode: null,
2243
2253
  source: null
2244
2254
  };
2255
+ var MAX_SETUP_LOG_CHARS = 256e3;
2256
+ function appendSetupOutput(prev, line, max = MAX_SETUP_LOG_CHARS) {
2257
+ const next = prev ? `${prev}
2258
+ ${line}` : line;
2259
+ if (next.length <= max) return next;
2260
+ const cut = next.slice(next.length - max);
2261
+ const nl = cut.indexOf("\n");
2262
+ return nl >= 0 && nl < cut.length - 1 ? cut.slice(nl + 1) : cut;
2263
+ }
2245
2264
  var memory = /* @__PURE__ */ new Map();
2246
2265
  var persistTimers = /* @__PURE__ */ new Map();
2247
2266
  function setupLogPath(threadId) {
@@ -2321,8 +2340,7 @@ function appendSetupLog(threadId, line) {
2321
2340
  const current = memory.get(threadId) ?? readSetupLog(threadId);
2322
2341
  const snap = {
2323
2342
  ...current,
2324
- output: current.output ? `${current.output}
2325
- ${line}` : line,
2343
+ output: appendSetupOutput(current.output, line),
2326
2344
  running: true
2327
2345
  };
2328
2346
  memory.set(threadId, snap);
@@ -6529,7 +6547,7 @@ function formatScheduledPrompt(name, prompt) {
6529
6547
  ${prompt}`;
6530
6548
  }
6531
6549
  async function defaultDeps() {
6532
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-2FTS55SG.js");
6550
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-L2H42HPW.js");
6533
6551
  const orch = getOrchestrator2();
6534
6552
  return {
6535
6553
  findThread: (id) => findThreadByRef(id),
@@ -7224,6 +7242,7 @@ var Orchestrator = class {
7224
7242
  return true;
7225
7243
  });
7226
7244
  if (!promoted) return this.requireThread(thread.id);
7245
+ if (!thisProcessShouldDrainAgentQueues()) return this.requireThread(thread.id);
7227
7246
  const current = this.requireThread(thread.id);
7228
7247
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
7229
7248
  const livePid = current.agentPid;
@@ -7964,10 +7983,10 @@ var Orchestrator = class {
7964
7983
  thread.id,
7965
7984
  ...threadsSharingWorktree(thread.worktreePath).map((t) => t.id)
7966
7985
  ];
7967
- const snap = pickRichestSetupLog([
7986
+ const snap = resolveWorktreeSetupLog(
7968
7987
  readSetupLog(setupLogKeyForWorktree(thread.worktreePath)),
7969
- ...[...new Set(siblingIds)].map((id) => readSetupLog(id))
7970
- ]) ?? readSetupLog(thread.id);
7988
+ [...new Set(siblingIds)].map((id) => readSetupLog(id))
7989
+ ) ?? readSetupLog(thread.id);
7971
7990
  if (snap.running && !this.hasWorktreeSetupProcess(thread.worktreePath)) {
7972
7991
  return { ...snap, running: false };
7973
7992
  }