@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.
package/dist/index.cjs CHANGED
@@ -801,6 +801,7 @@ function normalizeThread(raw) {
801
801
  planMode: Boolean(raw.planMode),
802
802
  autonomy: raw.autonomy ?? "default",
803
803
  lastError: raw.lastError ?? null,
804
+ agentPid: raw.agentPid ?? null,
804
805
  attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
805
806
  prTitle: raw.prTitle ?? null,
806
807
  userSetTitle: Boolean(raw.userSetTitle),
@@ -836,7 +837,8 @@ function createEmptyThread(partial) {
836
837
  worktreePath: partial.worktreePath,
837
838
  repoPath: partial.repoPath,
838
839
  agent: partial.agent,
839
- lastError: null
840
+ lastError: null,
841
+ agentPid: null
840
842
  };
841
843
  }
842
844
  async function withThreadLock(id, fn) {
@@ -5857,6 +5859,53 @@ var init_agents = __esm({
5857
5859
  }
5858
5860
  });
5859
5861
 
5862
+ // src/agents/cursor-recover.ts
5863
+ var cursor_recover_exports = {};
5864
+ __export(cursor_recover_exports, {
5865
+ recoverFinishedCursorRun: () => recoverFinishedCursorRun
5866
+ });
5867
+ function recoverFinishedCursorRun(opts) {
5868
+ const agentId = opts.agentId.trim();
5869
+ if (!agentId) return null;
5870
+ const runsPath = (0, import_node_path23.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
5871
+ if (!(0, import_node_fs24.existsSync)(runsPath)) return null;
5872
+ try {
5873
+ const lines = (0, import_node_fs24.readFileSync)(runsPath, "utf8").split("\n");
5874
+ let best = null;
5875
+ for (const line of lines) {
5876
+ const trimmed = line.trim();
5877
+ if (!trimmed) continue;
5878
+ let row;
5879
+ try {
5880
+ row = JSON.parse(trimmed);
5881
+ } catch {
5882
+ continue;
5883
+ }
5884
+ if (row.agentId !== agentId) continue;
5885
+ if (row.status !== "finished") continue;
5886
+ if (typeof row.result !== "string" || !row.result.trim()) continue;
5887
+ const endedAt = typeof row.endedAt === "number" ? row.endedAt : 0;
5888
+ const createdAt = typeof row.createdAt === "number" ? row.createdAt : 0;
5889
+ if (createdAt < opts.startedAfterMs && endedAt < opts.startedAfterMs) continue;
5890
+ if (!best || endedAt >= best.endedAt) {
5891
+ best = { runId: row.runId || "", result: row.result.trim(), endedAt };
5892
+ }
5893
+ }
5894
+ return best;
5895
+ } catch {
5896
+ return null;
5897
+ }
5898
+ }
5899
+ var import_node_fs24, import_node_path23;
5900
+ var init_cursor_recover = __esm({
5901
+ "src/agents/cursor-recover.ts"() {
5902
+ "use strict";
5903
+ import_node_fs24 = require("fs");
5904
+ import_node_path23 = require("path");
5905
+ init_paths();
5906
+ }
5907
+ });
5908
+
5860
5909
  // src/threads/title.ts
5861
5910
  var title_exports = {};
5862
5911
  __export(title_exports, {
@@ -5907,6 +5956,8 @@ __export(index_exports, {
5907
5956
  HARNESS_ENV_KEYS: () => HARNESS_ENV_KEYS,
5908
5957
  MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS: () => MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
5909
5958
  Orchestrator: () => Orchestrator,
5959
+ PASTE_ATTACH_MIN_CHARS: () => PASTE_ATTACH_MIN_CHARS,
5960
+ PASTE_ATTACH_MIN_LINES: () => PASTE_ATTACH_MIN_LINES,
5910
5961
  PLAN_MODE_INSTRUCTION: () => PLAN_MODE_INSTRUCTION,
5911
5962
  SIDEBOARD_FORCE_STOP: () => SIDEBOARD_FORCE_STOP,
5912
5963
  SIDEBOARD_MCP_ALLOWED_TOOLS: () => SIDEBOARD_MCP_ALLOWED_TOOLS,
@@ -5941,6 +5992,7 @@ __export(index_exports, {
5941
5992
  buildClaudeStreamJsonUserMessage: () => buildClaudeStreamJsonUserMessage,
5942
5993
  buildDiffCommentAttachment: () => buildDiffCommentAttachment,
5943
5994
  buildForkTranscriptAttachment: () => buildForkTranscriptAttachment,
5995
+ buildPastedTextAttachment: () => buildPastedTextAttachment,
5944
5996
  buildSessionSeed: () => buildSessionSeed,
5945
5997
  buildWorkspaceScriptEnv: () => buildWorkspaceScriptEnv,
5946
5998
  caffeinateWhileCloudConnectEnabled: () => caffeinateWhileCloudConnectEnabled,
@@ -6057,6 +6109,7 @@ __export(index_exports, {
6057
6109
  isImageFilePath: () => isImageFilePath,
6058
6110
  isLinearConnected: () => isLinearConnected,
6059
6111
  isOrchestratorThread: () => isOrchestratorThread,
6112
+ isPidAlive: () => isPidAlive,
6060
6113
  isPlaceholderBranch: () => isPlaceholderBranch,
6061
6114
  listAgentSetupInfo: () => listAgentSetupInfo,
6062
6115
  listBranchCommits: () => listBranchCommits,
@@ -6094,6 +6147,7 @@ __export(index_exports, {
6094
6147
  mcpAuthWarnings: () => mcpAuthWarnings,
6095
6148
  mergePr: () => mergePr,
6096
6149
  mergeUsage: () => mergeUsage,
6150
+ nextPastedTextName: () => nextPastedTextName,
6097
6151
  normalizeParseResult: () => normalizeParseResult,
6098
6152
  normalizeThread: () => normalizeThread,
6099
6153
  normalizeTurnInput: () => normalizeTurnInput,
@@ -6108,6 +6162,7 @@ __export(index_exports, {
6108
6162
  parseGithubSlugFromRemoteUrl: () => parseGithubSlugFromRemoteUrl,
6109
6163
  parseMcpList: () => parseMcpList,
6110
6164
  partsToAssistantText: () => partsToAssistantText,
6165
+ pastedTextStats: () => pastedTextStats,
6111
6166
  permissionMode: () => permissionMode,
6112
6167
  previewLand: () => previewLand,
6113
6168
  pushBranch: () => pushBranch,
@@ -6143,6 +6198,7 @@ __export(index_exports, {
6143
6198
  saveAppSettings: () => saveAppSettings,
6144
6199
  setStatus: () => setStatus,
6145
6200
  settingsSourceLabel: () => settingsSourceLabel,
6201
+ shouldAttachPastedText: () => shouldAttachPastedText,
6146
6202
  shouldCompactContext: () => shouldCompactContext,
6147
6203
  shouldRunWorktreeCleanup: () => shouldRunWorktreeCleanup,
6148
6204
  sideboardHomeDir: () => sideboardHomeDir,
@@ -6479,12 +6535,20 @@ function diffFromInput(input) {
6479
6535
  }
6480
6536
  function parseDiffStat(result) {
6481
6537
  if (!result) return {};
6482
- const plus = result.match(/\+(\d+)/);
6483
- const minus = result.match(/-(\d+)/);
6484
- if (plus || minus) {
6538
+ const paired = result.match(/\+(\d+)\s+-(\d+)/);
6539
+ if (paired) {
6540
+ return {
6541
+ additions: Number(paired[1]),
6542
+ deletions: Number(paired[2])
6543
+ };
6544
+ }
6545
+ const verbose = result.match(
6546
+ /(\d+)\s+insertions?(?:,\s*(\d+)\s+deletions?)?/i
6547
+ );
6548
+ if (verbose) {
6485
6549
  return {
6486
- additions: plus ? Number(plus[1]) : void 0,
6487
- deletions: minus ? Number(minus[1]) : void 0
6550
+ additions: Number(verbose[1]),
6551
+ deletions: verbose[2] != null ? Number(verbose[2]) : void 0
6488
6552
  };
6489
6553
  }
6490
6554
  return {};
@@ -6556,8 +6620,8 @@ function applyAgentEvent(parts, event) {
6556
6620
  ...p,
6557
6621
  status: event.isError ? "error" : "done",
6558
6622
  result: event.content,
6559
- additions: fromResult.additions ?? p.additions,
6560
- deletions: fromResult.deletions ?? p.deletions
6623
+ ...fromResult.additions != null ? { additions: fromResult.additions } : {},
6624
+ ...fromResult.deletions != null ? { deletions: fromResult.deletions } : {}
6561
6625
  };
6562
6626
  });
6563
6627
  return next;
@@ -8323,6 +8387,42 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
8323
8387
  return out;
8324
8388
  }
8325
8389
 
8390
+ // src/composer/pasted-text.ts
8391
+ var import_node_crypto3 = require("crypto");
8392
+ var PASTE_ATTACH_MIN_CHARS = 1200;
8393
+ var PASTE_ATTACH_MIN_LINES = 15;
8394
+ var PASTED_NAME_RE = /^Pasted text #(\d+)\.txt$/i;
8395
+ var PASTED_NAME_ALT_RE = /^pasted-(\d+)\.txt$/i;
8396
+ function pastedTextStats(text) {
8397
+ const chars = text.length;
8398
+ if (chars === 0) return { chars: 0, lines: 0 };
8399
+ const lines = text.split(/\r\n|\r|\n/).length;
8400
+ return { chars, lines };
8401
+ }
8402
+ function shouldAttachPastedText(text) {
8403
+ const trimmed = text.trim();
8404
+ if (!trimmed) return false;
8405
+ const { chars, lines } = pastedTextStats(text);
8406
+ return chars >= PASTE_ATTACH_MIN_CHARS || lines >= PASTE_ATTACH_MIN_LINES;
8407
+ }
8408
+ function nextPastedTextName(existing) {
8409
+ let max = 0;
8410
+ for (const a of existing) {
8411
+ const m = PASTED_NAME_RE.exec(a.name) ?? PASTED_NAME_ALT_RE.exec(a.name);
8412
+ if (m?.[1]) max = Math.max(max, Number(m[1]));
8413
+ }
8414
+ return `Pasted text #${max + 1}.txt`;
8415
+ }
8416
+ function buildPastedTextAttachment(text, opts) {
8417
+ return {
8418
+ id: opts?.id ?? (0, import_node_crypto3.randomUUID)(),
8419
+ name: opts?.name ?? "Pasted text #1.txt",
8420
+ kind: "file",
8421
+ path: opts?.path,
8422
+ content: text
8423
+ };
8424
+ }
8425
+
8326
8426
  // src/composer/summarize.ts
8327
8427
  init_run();
8328
8428
  init_path();
@@ -8851,7 +8951,7 @@ async function listLinearIssues(agent, repoPath) {
8851
8951
  }
8852
8952
 
8853
8953
  // src/threads/chat-tabs.ts
8854
- var import_node_crypto3 = require("crypto");
8954
+ var import_node_crypto4 = require("crypto");
8855
8955
  init_teams();
8856
8956
  init_worktree_labels();
8857
8957
  init_global_workspace();
@@ -8907,7 +9007,7 @@ function forkMessageSlice(from, throughIndex) {
8907
9007
  function buildForkTranscriptAttachment(baseTitle, messages) {
8908
9008
  const title = baseTitle || "Chat";
8909
9009
  return {
8910
- id: (0, import_node_crypto3.randomUUID)(),
9010
+ id: (0, import_node_crypto4.randomUUID)(),
8911
9011
  name: `Transcript of ${title}.md`,
8912
9012
  kind: "transcript",
8913
9013
  content: formatTranscriptMarkdown(title, messages)
@@ -9262,7 +9362,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
9262
9362
 
9263
9363
  // src/orchestrator/orchestrator.ts
9264
9364
  var import_node_events = require("events");
9265
- var import_node_fs24 = require("fs");
9365
+ var import_node_fs25 = require("fs");
9266
9366
  init_error_detail();
9267
9367
  init_agents();
9268
9368
  init_worktree();
@@ -9546,6 +9646,15 @@ async function syncThreadBranchFromGit(threadId) {
9546
9646
  init_workspaces();
9547
9647
  init_global_workspace();
9548
9648
  init_coordinator_prompt();
9649
+ function isPidAlive(pid) {
9650
+ if (!Number.isFinite(pid) || pid <= 0) return false;
9651
+ try {
9652
+ process.kill(pid, 0);
9653
+ return true;
9654
+ } catch {
9655
+ return false;
9656
+ }
9657
+ }
9549
9658
  var Orchestrator = class {
9550
9659
  events = new import_node_events.EventEmitter();
9551
9660
  processes = /* @__PURE__ */ new Map();
@@ -9582,8 +9691,18 @@ var Orchestrator = class {
9582
9691
  isStaleRunningThread(threadId, status) {
9583
9692
  return status === "running" && !this.activeTurns.has(threadId) && !this.startingTurns.has(threadId);
9584
9693
  }
9694
+ /**
9695
+ * Cross-process guard: another Sideboard process (MCP stdio) may call reconcile
9696
+ * while the desktop still owns a live agent child. Never reclaim those.
9697
+ */
9698
+ shouldReclaimRunningThread(thread) {
9699
+ if (!this.isStaleRunningThread(thread.id, thread.status)) return false;
9700
+ const pid = thread.agentPid;
9701
+ if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
9702
+ return true;
9703
+ }
9585
9704
  async reconcile(repoPath, opts) {
9586
- const reclaimStaleTurns = opts?.reclaimStaleTurns !== false;
9705
+ const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
9587
9706
  healOrchestrationSoccerTitles();
9588
9707
  for (const thread of listThreads({ includeArchived: true })) {
9589
9708
  if (thread.status === "archived") continue;
@@ -9599,18 +9718,18 @@ var Orchestrator = class {
9599
9718
  if (Object.keys(heal).length) {
9600
9719
  updateThread(thread.id, heal);
9601
9720
  }
9602
- if (reclaimStaleTurns && this.isStaleRunningThread(thread.id, thread.status)) {
9721
+ if (reclaimStaleTurns && this.shouldReclaimRunningThread(thread)) {
9603
9722
  setStatus(thread.id, "stopped", "Process died (reconciled on startup)");
9604
9723
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
9605
9724
  }
9606
9725
  continue;
9607
9726
  }
9608
- if (!(0, import_node_fs24.existsSync)(thread.worktreePath)) {
9727
+ if (!(0, import_node_fs25.existsSync)(thread.worktreePath)) {
9609
9728
  setStatus(thread.id, "broken", "Worktree missing on disk");
9610
9729
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
9611
9730
  continue;
9612
9731
  }
9613
- if (reclaimStaleTurns && this.isStaleRunningThread(thread.id, thread.status)) {
9732
+ if (reclaimStaleTurns && this.shouldReclaimRunningThread(thread)) {
9614
9733
  setStatus(thread.id, "stopped", "Process died (reconciled on startup)");
9615
9734
  this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
9616
9735
  }
@@ -9792,6 +9911,11 @@ var Orchestrator = class {
9792
9911
  await new Promise((r) => setTimeout(r, 100));
9793
9912
  continue;
9794
9913
  }
9914
+ const livePid = thread.agentPid;
9915
+ if (typeof livePid === "number" && livePid > 0 && isPidAlive(livePid)) {
9916
+ await new Promise((r) => setTimeout(r, 200));
9917
+ continue;
9918
+ }
9795
9919
  const prompt = thread.queue[0];
9796
9920
  const remaining = thread.queue.slice(1);
9797
9921
  updateThread(threadId, { queue: remaining });
@@ -9935,10 +10059,18 @@ var Orchestrator = class {
9935
10059
  if (event.type === "stderr" && typeof event.data === "string") {
9936
10060
  pushTurnStderr(stderrTail, event.data);
9937
10061
  }
10062
+ const live = readThread(threadId);
10063
+ if (live?.lastError?.includes("reconciled on startup") && (this.activeTurns.has(threadId) || this.startingTurns.has(threadId))) {
10064
+ setStatus(threadId, "running");
10065
+ this.emit({ type: "status_changed", threadId, status: "running" });
10066
+ }
9938
10067
  }
9939
10068
  );
9940
10069
  this.activeTurns.set(threadId, handle);
9941
10070
  this.startingTurns.delete(threadId);
10071
+ if (typeof handle.pid === "number" && handle.pid > 0) {
10072
+ updateThread(threadId, { agentPid: handle.pid });
10073
+ }
9942
10074
  if (this.stoppedTurns.has(threadId)) {
9943
10075
  handle.kill();
9944
10076
  } else {
@@ -9958,20 +10090,41 @@ var Orchestrator = class {
9958
10090
  if (result.sessionId) {
9959
10091
  updateThread(threadId, { sessionId: result.sessionId });
9960
10092
  }
9961
- const assistantText = result.assistantText.trim();
9962
- const failureOnlyMessage = result.exitCode !== 0 && looksLikeAgentFailureMessage(assistantText) && !result.parts.some((p) => p.type === "tool" || p.type === "thinking");
9963
- if (!failureOnlyMessage && (assistantText || result.parts.length > 0)) {
10093
+ let assistantText = result.assistantText.trim();
10094
+ let parts = result.parts;
10095
+ let usage = result.usage ?? void 0;
10096
+ let exitCode = result.exitCode;
10097
+ if (this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
10098
+ const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
10099
+ if (sessionId) {
10100
+ const { recoverFinishedCursorRun: recoverFinishedCursorRun2 } = await Promise.resolve().then(() => (init_cursor_recover(), cursor_recover_exports));
10101
+ for (let i = 0; i < 8; i++) {
10102
+ const recovered = recoverFinishedCursorRun2({
10103
+ agentId: sessionId,
10104
+ startedAfterMs: turnStartedAt - 5e3
10105
+ });
10106
+ if (recovered?.result) {
10107
+ assistantText = recovered.result;
10108
+ exitCode = 0;
10109
+ break;
10110
+ }
10111
+ await new Promise((r) => setTimeout(r, 500));
10112
+ }
10113
+ }
10114
+ }
10115
+ const failureOnlyMessage = exitCode !== 0 && looksLikeAgentFailureMessage(assistantText) && !parts.some((p) => p.type === "tool" || p.type === "thinking");
10116
+ if (!failureOnlyMessage && (assistantText || parts.length > 0)) {
9964
10117
  appendMessage(threadId, {
9965
10118
  role: "agent",
9966
10119
  text: assistantText,
9967
- parts: result.parts.length > 0 ? result.parts : void 0,
10120
+ parts: parts.length > 0 ? parts : void 0,
9968
10121
  durationMs: Math.max(0, Date.now() - turnStartedAt),
9969
- usage: result.usage ?? void 0,
10122
+ usage,
9970
10123
  ts: (/* @__PURE__ */ new Date()).toISOString()
9971
10124
  });
9972
10125
  }
9973
10126
  const afterTurn = this.requireThread(threadId);
9974
- if (afterTurn.planMode && afterTurn.agent === "claude" && result.parts.some(
10127
+ if (afterTurn.planMode && afterTurn.agent === "claude" && parts.some(
9975
10128
  (p) => p.type === "tool" && /exitplanmode/i.test(p.name)
9976
10129
  )) {
9977
10130
  updateThread(threadId, { sessionId: null });
@@ -9980,22 +10133,22 @@ var Orchestrator = class {
9980
10133
  if (this.stoppedTurns.has(threadId)) {
9981
10134
  setStatus(threadId, "stopped");
9982
10135
  this.emit({ type: "status_changed", threadId, status: "stopped" });
9983
- this.emit({ type: "turn_finished", threadId, exitCode: result.exitCode });
10136
+ this.emit({ type: "turn_finished", threadId, exitCode });
9984
10137
  } else {
9985
10138
  const lastStderr = summarizeTurnStderr(stderrTail);
9986
- const detail = lastStderr || (result.exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
9987
- const failDetail = formatTurnExitError(result.exitCode, detail);
10139
+ const detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
10140
+ const failDetail = formatTurnExitError(exitCode, detail);
9988
10141
  setStatus(
9989
10142
  threadId,
9990
- result.exitCode === 0 ? "idle" : "error",
9991
- result.exitCode === 0 ? null : failDetail
10143
+ exitCode === 0 ? "idle" : "error",
10144
+ exitCode === 0 ? null : failDetail
9992
10145
  );
9993
10146
  this.emit({
9994
10147
  type: "status_changed",
9995
10148
  threadId,
9996
- status: result.exitCode === 0 ? "idle" : "error"
10149
+ status: exitCode === 0 ? "idle" : "error"
9997
10150
  });
9998
- this.emit({ type: "turn_finished", threadId, exitCode: result.exitCode });
10151
+ this.emit({ type: "turn_finished", threadId, exitCode });
9999
10152
  }
10000
10153
  } catch (err) {
10001
10154
  const message = err instanceof Error ? err.message : String(err);
@@ -10016,6 +10169,10 @@ var Orchestrator = class {
10016
10169
  this.processes.delete(`${threadId}:agent`);
10017
10170
  this.stoppedTurns.delete(threadId);
10018
10171
  this.runningCount = Math.max(0, this.runningCount - 1);
10172
+ try {
10173
+ updateThread(threadId, { agentPid: null });
10174
+ } catch {
10175
+ }
10019
10176
  }
10020
10177
  }
10021
10178
  /**
@@ -10588,7 +10745,7 @@ var Orchestrator = class {
10588
10745
  updateThread(thread.id, { worktreePath: globalAgentCwd2() });
10589
10746
  return setStatus(thread.id, "idle");
10590
10747
  }
10591
- if (!(0, import_node_fs24.existsSync)(thread.worktreePath)) {
10748
+ if (!(0, import_node_fs25.existsSync)(thread.worktreePath)) {
10592
10749
  const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
10593
10750
  const { execa: execa7 } = await import("execa");
10594
10751
  const slug = thread.worktreePath.split("/").pop();
@@ -10700,7 +10857,7 @@ init_coordinator_prompt();
10700
10857
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
10701
10858
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
10702
10859
  var import_zod = require("zod");
10703
- var import_node_path23 = require("path");
10860
+ var import_node_path24 = require("path");
10704
10861
  init_worktree();
10705
10862
  init_global_workspace();
10706
10863
 
@@ -10748,7 +10905,7 @@ async function startMcpServer() {
10748
10905
  async () => {
10749
10906
  const threads = orch.getThreads(true);
10750
10907
  const lines = threads.map((t) => {
10751
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path23.basename)(t.repoPath) || t.repoPath;
10908
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path24.basename)(t.repoPath) || t.repoPath;
10752
10909
  return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
10753
10910
  });
10754
10911
  return {
@@ -11631,6 +11788,8 @@ init_injected_mcp();
11631
11788
  HARNESS_ENV_KEYS,
11632
11789
  MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS,
11633
11790
  Orchestrator,
11791
+ PASTE_ATTACH_MIN_CHARS,
11792
+ PASTE_ATTACH_MIN_LINES,
11634
11793
  PLAN_MODE_INSTRUCTION,
11635
11794
  SIDEBOARD_FORCE_STOP,
11636
11795
  SIDEBOARD_MCP_ALLOWED_TOOLS,
@@ -11665,6 +11824,7 @@ init_injected_mcp();
11665
11824
  buildClaudeStreamJsonUserMessage,
11666
11825
  buildDiffCommentAttachment,
11667
11826
  buildForkTranscriptAttachment,
11827
+ buildPastedTextAttachment,
11668
11828
  buildSessionSeed,
11669
11829
  buildWorkspaceScriptEnv,
11670
11830
  caffeinateWhileCloudConnectEnabled,
@@ -11781,6 +11941,7 @@ init_injected_mcp();
11781
11941
  isImageFilePath,
11782
11942
  isLinearConnected,
11783
11943
  isOrchestratorThread,
11944
+ isPidAlive,
11784
11945
  isPlaceholderBranch,
11785
11946
  listAgentSetupInfo,
11786
11947
  listBranchCommits,
@@ -11818,6 +11979,7 @@ init_injected_mcp();
11818
11979
  mcpAuthWarnings,
11819
11980
  mergePr,
11820
11981
  mergeUsage,
11982
+ nextPastedTextName,
11821
11983
  normalizeParseResult,
11822
11984
  normalizeThread,
11823
11985
  normalizeTurnInput,
@@ -11832,6 +11994,7 @@ init_injected_mcp();
11832
11994
  parseGithubSlugFromRemoteUrl,
11833
11995
  parseMcpList,
11834
11996
  partsToAssistantText,
11997
+ pastedTextStats,
11835
11998
  permissionMode,
11836
11999
  previewLand,
11837
12000
  pushBranch,
@@ -11867,6 +12030,7 @@ init_injected_mcp();
11867
12030
  saveAppSettings,
11868
12031
  setStatus,
11869
12032
  settingsSourceLabel,
12033
+ shouldAttachPastedText,
11870
12034
  shouldCompactContext,
11871
12035
  shouldRunWorktreeCleanup,
11872
12036
  sideboardHomeDir,
package/dist/index.d.cts CHANGED
@@ -92,6 +92,11 @@ interface Thread {
92
92
  /** Pending composer attachments (forked transcripts, etc.). */
93
93
  attachments: ThreadAttachment[];
94
94
  lastError?: string | null;
95
+ /**
96
+ * OS pid of the in-flight agent child while status is `running`.
97
+ * Used so other processes (MCP) do not reclaim a live turn as dead.
98
+ */
99
+ agentPid?: number | null;
95
100
  }
96
101
  interface CreateChatTabInput {
97
102
  /** Existing thread in the worktree to clone workspace metadata from. */
@@ -1637,6 +1642,33 @@ declare function attachmentsFromBuffers(buffers: ComposerFileBuffer[]): ThreadAt
1637
1642
  */
1638
1643
  declare function attachmentsFromWorktreePaths(worktreePath: string, relativePaths: string[]): ThreadAttachment[];
1639
1644
 
1645
+ /** Paste this large → attach as a doc chip instead of flooding the composer. */
1646
+ declare const PASTE_ATTACH_MIN_CHARS = 1200;
1647
+ /** Or this many lines (whichever hits first). */
1648
+ declare const PASTE_ATTACH_MIN_LINES = 15;
1649
+ declare function pastedTextStats(text: string): {
1650
+ chars: number;
1651
+ lines: number;
1652
+ };
1653
+ /**
1654
+ * True when clipboard text is large enough that Claude-style doc attachment
1655
+ * is preferable to dumping it into the message input.
1656
+ */
1657
+ declare function shouldAttachPastedText(text: string): boolean;
1658
+ /** Next `Pasted text #N.txt` name given existing composer attachments. */
1659
+ declare function nextPastedTextName(existing: Array<{
1660
+ name: string;
1661
+ }>): string;
1662
+ /**
1663
+ * Build a file-kind attachment for a large paste. Content is expanded into the
1664
+ * agent prompt via `expandComposerPrompt` like other composer attachments.
1665
+ */
1666
+ declare function buildPastedTextAttachment(text: string, opts?: {
1667
+ name?: string;
1668
+ id?: string;
1669
+ path?: string;
1670
+ }): ThreadAttachment;
1671
+
1640
1672
  interface SummarizeResult {
1641
1673
  summary: string;
1642
1674
  method: 'claude' | 'extractive';
@@ -1787,6 +1819,9 @@ declare function applyThreadIntoMain(thread: Pick<Thread, 'repoPath' | 'worktree
1787
1819
  targetBranch?: string;
1788
1820
  }): Promise<ApplyIntoMainResult>;
1789
1821
 
1822
+ /** True when `kill(pid, 0)` succeeds (process exists and is signalable). */
1823
+ declare function isPidAlive(pid: number): boolean;
1824
+
1790
1825
  declare class Orchestrator {
1791
1826
  readonly events: EventEmitter<[never]>;
1792
1827
  private readonly processes;
@@ -1816,11 +1851,17 @@ declare class Orchestrator {
1816
1851
  private emit;
1817
1852
  /** True when disk says running but this process is not actually turning. */
1818
1853
  private isStaleRunningThread;
1854
+ /**
1855
+ * Cross-process guard: another Sideboard process (MCP stdio) may call reconcile
1856
+ * while the desktop still owns a live agent child. Never reclaim those.
1857
+ */
1858
+ private shouldReclaimRunningThread;
1819
1859
  reconcile(repoPath?: string, opts?: {
1820
1860
  /**
1821
- * When true (default), mark disk-status `running` threads with no in-process
1822
- * turn as stopped. Must stay false in Sideboard MCP subprocesses — they do
1823
- * not own agent turns, so every live parent turn looks "dead".
1861
+ * When true, mark disk-status `running` threads with no in-process turn
1862
+ * (and no live agentPid) as stopped. Default false MCP/CLI helpers must
1863
+ * not reclaim turns owned by the desktop orchestrator. Pass true only on
1864
+ * real app/CLI startup recovery.
1824
1865
  */
1825
1866
  reclaimStaleTurns?: boolean;
1826
1867
  }): Promise<void>;
@@ -2636,4 +2677,4 @@ declare function writeInjectedMcpConfig(opts: {
2636
2677
  includeBrightsy?: boolean;
2637
2678
  }): Promise<string | null>;
2638
2679
 
2639
- export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorModelInfo, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DefaultsAppSettings, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getAgentSetupInfo, getBrightsySession, getDefaultAgent, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, installAgent, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isCursorAutoModel, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isLinearConnected, isOrchestratorThread, isPlaceholderBranch, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listOpencodeModels, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveThreadDefaults, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateDefaultsSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };
2680
+ export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorModelInfo, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DefaultsAppSettings, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PASTE_ATTACH_MIN_CHARS, PASTE_ATTACH_MIN_LINES, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildPastedTextAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getAgentSetupInfo, getBrightsySession, getDefaultAgent, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, installAgent, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isCursorAutoModel, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isLinearConnected, isOrchestratorThread, isPidAlive, isPlaceholderBranch, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listOpencodeModels, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, nextPastedTextName, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, pastedTextStats, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveThreadDefaults, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldAttachPastedText, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateDefaultsSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };