@sideboard-ai/core 0.1.96 → 0.1.98

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.
@@ -28,13 +28,13 @@ import {
28
28
  resolveCursorModelId,
29
29
  resolveLoginCommand,
30
30
  resolveQuotaFallbackAgent
31
- } from "./chunk-KWNUZ4LR.js";
31
+ } from "./chunk-MBP3XG57.js";
32
32
  import {
33
33
  ORCHESTRATOR_AGENT_KINDS,
34
34
  assertOrchestratorCapableAgent,
35
35
  coerceOrchestratorAgent,
36
36
  isOrchestratorCapableAgent
37
- } from "./chunk-CLGO7TLO.js";
37
+ } from "./chunk-FO67IJTY.js";
38
38
  import "./chunk-XUWDLRAE.js";
39
39
  import "./chunk-QSLE4VEM.js";
40
40
  import {
@@ -32,14 +32,14 @@ import {
32
32
  resolveCursorModelId,
33
33
  resolveLoginCommand,
34
34
  resolveQuotaFallbackAgent
35
- } from "./chunk-WBX46OPD.js";
35
+ } from "./chunk-FYS2BULQ.js";
36
36
  import "./chunk-DKHGWYWR.js";
37
37
  import {
38
38
  ORCHESTRATOR_AGENT_KINDS,
39
39
  assertOrchestratorCapableAgent,
40
40
  coerceOrchestratorAgent,
41
41
  isOrchestratorCapableAgent
42
- } from "./chunk-NR6APJLD.js";
42
+ } from "./chunk-HI2OTFFR.js";
43
43
  import "./chunk-XH2GS2LO.js";
44
44
  import "./chunk-R7BQBSDT.js";
45
45
  import "./chunk-B3SJXYIJ.js";
@@ -209,42 +209,40 @@ function findSlackCoordinator(teamId, userId) {
209
209
  (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
210
210
  );
211
211
  }
212
- function ensureSlackCoordinator(teamId, userId, agent) {
212
+ function ensureSlackCoordinator(teamId, userId, agent, opts) {
213
213
  const defaults = resolveThreadDefaults();
214
214
  const desired = assertOrchestratorCapableAgent(agent);
215
215
  const ref = slackCoordinatorSourceRef(teamId, userId);
216
- const existing = findSlackCoordinator(teamId, userId);
217
- if (existing) {
218
- const patch = {};
219
- if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
220
- patch.repoPath = GLOBAL_WORKSPACE_ID;
221
- patch.worktreePath = globalAgentCwd();
222
- patch.branchName = "global";
223
- }
224
- const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
225
- const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
226
- if (canRetarget) {
227
- if (existing.agent !== desired) patch.agent = desired;
228
- if (existing.model !== defaults.model) patch.model = defaults.model;
229
- if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
230
- if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
231
- }
232
- if (Object.keys(patch).length > 0) {
233
- return updateThread(existing.id, patch);
216
+ if (!opts?.forceNew) {
217
+ const existing = findSlackCoordinator(teamId, userId);
218
+ if (existing) {
219
+ const patch = {};
220
+ if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
221
+ patch.repoPath = GLOBAL_WORKSPACE_ID;
222
+ patch.worktreePath = globalAgentCwd();
223
+ patch.branchName = "global";
224
+ }
225
+ const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
226
+ const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
227
+ if (canRetarget) {
228
+ if (existing.agent !== desired) patch.agent = desired;
229
+ if (existing.model !== defaults.model) patch.model = defaults.model;
230
+ if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
231
+ if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
232
+ }
233
+ if (Object.keys(patch).length > 0) {
234
+ return updateThread(existing.id, patch);
235
+ }
236
+ return existing;
234
237
  }
235
- return existing;
236
238
  }
237
- const created = createGlobalChat({
239
+ return createGlobalChat({
238
240
  sourceRef: ref,
239
241
  agent: desired,
240
242
  model: defaults.model,
241
243
  effort: defaults.effort,
242
244
  fast: defaults.fast
243
245
  });
244
- const all = listThreads({ includeArchived: true }).filter(
245
- (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
246
- ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
247
- return all[0] ?? created;
248
246
  }
249
247
  function ensureCloudCoordinator(agent) {
250
248
  const defaults = resolveThreadDefaults();
@@ -307,6 +305,7 @@ export {
307
305
  listGlobalThreads,
308
306
  slackCoordinatorSourceRef,
309
307
  isSlackCoordinatorThread,
308
+ findSlackCoordinator,
310
309
  ensureSlackCoordinator,
311
310
  ensureCloudCoordinator
312
311
  };
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-DKHGWYWR.js";
10
10
  import {
11
11
  isOrchestratorThread
12
- } from "./chunk-NR6APJLD.js";
12
+ } from "./chunk-HI2OTFFR.js";
13
13
  import {
14
14
  codexUnattendedGitConfigArgs,
15
15
  mergeAgentGitAuthEnv,
@@ -1208,7 +1208,7 @@ var claudeAdapter = {
1208
1208
  );
1209
1209
  }
1210
1210
  const mode = permissionMode(thread);
1211
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-3GNPQCLE.js");
1211
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-WMF3BJP5.js");
1212
1212
  const isOrchestrator = isOrchestratorThread2(thread);
1213
1213
  const injectedServers = await buildInjectedMcpServers({
1214
1214
  includeSideboard: true,
@@ -203,42 +203,40 @@ function findSlackCoordinator(teamId, userId) {
203
203
  (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
204
204
  );
205
205
  }
206
- function ensureSlackCoordinator(teamId, userId, agent) {
206
+ function ensureSlackCoordinator(teamId, userId, agent, opts) {
207
207
  const defaults = resolveThreadDefaults();
208
208
  const desired = assertOrchestratorCapableAgent(agent);
209
209
  const ref = slackCoordinatorSourceRef(teamId, userId);
210
- const existing = findSlackCoordinator(teamId, userId);
211
- if (existing) {
212
- const patch = {};
213
- if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
214
- patch.repoPath = GLOBAL_WORKSPACE_ID;
215
- patch.worktreePath = globalAgentCwd();
216
- patch.branchName = "global";
217
- }
218
- const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
219
- const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
220
- if (canRetarget) {
221
- if (existing.agent !== desired) patch.agent = desired;
222
- if (existing.model !== defaults.model) patch.model = defaults.model;
223
- if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
224
- if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
225
- }
226
- if (Object.keys(patch).length > 0) {
227
- return updateThread(existing.id, patch);
210
+ if (!opts?.forceNew) {
211
+ const existing = findSlackCoordinator(teamId, userId);
212
+ if (existing) {
213
+ const patch = {};
214
+ if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
215
+ patch.repoPath = GLOBAL_WORKSPACE_ID;
216
+ patch.worktreePath = globalAgentCwd();
217
+ patch.branchName = "global";
218
+ }
219
+ const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
220
+ const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
221
+ if (canRetarget) {
222
+ if (existing.agent !== desired) patch.agent = desired;
223
+ if (existing.model !== defaults.model) patch.model = defaults.model;
224
+ if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
225
+ if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
226
+ }
227
+ if (Object.keys(patch).length > 0) {
228
+ return updateThread(existing.id, patch);
229
+ }
230
+ return existing;
228
231
  }
229
- return existing;
230
232
  }
231
- const created = createGlobalChat({
233
+ return createGlobalChat({
232
234
  sourceRef: ref,
233
235
  agent: desired,
234
236
  model: defaults.model,
235
237
  effort: defaults.effort,
236
238
  fast: defaults.fast
237
239
  });
238
- const all = listThreads({ includeArchived: true }).filter(
239
- (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
240
- ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
241
- return all[0] ?? created;
242
240
  }
243
241
  function ensureCloudCoordinator(agent) {
244
242
  const defaults = resolveThreadDefaults();
@@ -295,6 +293,7 @@ export {
295
293
  listGlobalThreads,
296
294
  slackCoordinatorSourceRef,
297
295
  isSlackCoordinatorThread,
296
+ findSlackCoordinator,
298
297
  ensureSlackCoordinator,
299
298
  ensureCloudCoordinator
300
299
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isOrchestratorThread
3
- } from "./chunk-CLGO7TLO.js";
3
+ } from "./chunk-FO67IJTY.js";
4
4
  import {
5
5
  applyConnectedTeamToCli,
6
6
  brightsyMcpServerName,
@@ -1019,7 +1019,7 @@ var claudeAdapter = {
1019
1019
  );
1020
1020
  }
1021
1021
  const mode = permissionMode(thread);
1022
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-M3OMVDDH.js");
1022
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-RSQXRLT7.js");
1023
1023
  const isOrchestrator = isOrchestratorThread2(thread);
1024
1024
  const injectedServers = await buildInjectedMcpServers({
1025
1025
  includeSideboard: true,
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {
4
4
  isGlobalRepoPath
5
- } from "./chunk-NR6APJLD.js";
5
+ } from "./chunk-HI2OTFFR.js";
6
6
  import {
7
7
  ensureGhPreferOrigin,
8
8
  resolveRepoRoot
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isGlobalRepoPath
3
- } from "./chunk-CLGO7TLO.js";
3
+ } from "./chunk-FO67IJTY.js";
4
4
  import {
5
5
  ensureGhPreferOrigin,
6
6
  resolveRepoRoot
@@ -3,6 +3,7 @@ import {
3
3
  createGlobalChat,
4
4
  ensureCloudCoordinator,
5
5
  ensureSlackCoordinator,
6
+ findSlackCoordinator,
6
7
  healOrchestrationSoccerTitles,
7
8
  isCloudCoordinatorThread,
8
9
  isGlobalRepoPath,
@@ -14,7 +15,7 @@ import {
14
15
  orchestratorSessionPoisonedByBuiltins,
15
16
  slackCoordinatorSourceRef,
16
17
  takenTeamSlugsForOrchestration
17
- } from "./chunk-CLGO7TLO.js";
18
+ } from "./chunk-FO67IJTY.js";
18
19
  import "./chunk-XUWDLRAE.js";
19
20
  import "./chunk-CIRXAYWS.js";
20
21
  import "./chunk-FKOIHGKV.js";
@@ -32,6 +33,7 @@ export {
32
33
  createGlobalChat,
33
34
  ensureCloudCoordinator,
34
35
  ensureSlackCoordinator,
36
+ findSlackCoordinator,
35
37
  globalAgentCwd,
36
38
  healOrchestrationSoccerTitles,
37
39
  isCloudCoordinatorThread,
@@ -5,6 +5,7 @@ import {
5
5
  createGlobalChat,
6
6
  ensureCloudCoordinator,
7
7
  ensureSlackCoordinator,
8
+ findSlackCoordinator,
8
9
  healOrchestrationSoccerTitles,
9
10
  isCloudCoordinatorThread,
10
11
  isGlobalRepoPath,
@@ -16,7 +17,7 @@ import {
16
17
  orchestratorSessionPoisonedByBuiltins,
17
18
  slackCoordinatorSourceRef,
18
19
  takenTeamSlugsForOrchestration
19
- } from "./chunk-NR6APJLD.js";
20
+ } from "./chunk-HI2OTFFR.js";
20
21
  import "./chunk-XH2GS2LO.js";
21
22
  import "./chunk-R7BQBSDT.js";
22
23
  import "./chunk-B3SJXYIJ.js";
@@ -33,6 +34,7 @@ export {
33
34
  createGlobalChat,
34
35
  ensureCloudCoordinator,
35
36
  ensureSlackCoordinator,
37
+ findSlackCoordinator,
36
38
  globalAgentCwd,
37
39
  healOrchestrationSoccerTitles,
38
40
  isCloudCoordinatorThread,
package/dist/index.cjs CHANGED
@@ -5307,6 +5307,7 @@ __export(global_workspace_exports, {
5307
5307
  createGlobalChat: () => createGlobalChat,
5308
5308
  ensureCloudCoordinator: () => ensureCloudCoordinator,
5309
5309
  ensureSlackCoordinator: () => ensureSlackCoordinator,
5310
+ findSlackCoordinator: () => findSlackCoordinator,
5310
5311
  globalAgentCwd: () => globalAgentCwd,
5311
5312
  healOrchestrationSoccerTitles: () => healOrchestrationSoccerTitles,
5312
5313
  isCloudCoordinatorThread: () => isCloudCoordinatorThread,
@@ -5453,42 +5454,40 @@ function findSlackCoordinator(teamId, userId) {
5453
5454
  (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
5454
5455
  );
5455
5456
  }
5456
- function ensureSlackCoordinator(teamId, userId, agent) {
5457
+ function ensureSlackCoordinator(teamId, userId, agent, opts) {
5457
5458
  const defaults = resolveThreadDefaults();
5458
5459
  const desired = assertOrchestratorCapableAgent(agent);
5459
5460
  const ref = slackCoordinatorSourceRef(teamId, userId);
5460
- const existing = findSlackCoordinator(teamId, userId);
5461
- if (existing) {
5462
- const patch = {};
5463
- if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
5464
- patch.repoPath = GLOBAL_WORKSPACE_ID;
5465
- patch.worktreePath = globalAgentCwd();
5466
- patch.branchName = "global";
5467
- }
5468
- const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
5469
- const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
5470
- if (canRetarget) {
5471
- if (existing.agent !== desired) patch.agent = desired;
5472
- if (existing.model !== defaults.model) patch.model = defaults.model;
5473
- if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
5474
- if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
5475
- }
5476
- if (Object.keys(patch).length > 0) {
5477
- return updateThread(existing.id, patch);
5461
+ if (!opts?.forceNew) {
5462
+ const existing = findSlackCoordinator(teamId, userId);
5463
+ if (existing) {
5464
+ const patch = {};
5465
+ if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
5466
+ patch.repoPath = GLOBAL_WORKSPACE_ID;
5467
+ patch.worktreePath = globalAgentCwd();
5468
+ patch.branchName = "global";
5469
+ }
5470
+ const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
5471
+ const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
5472
+ if (canRetarget) {
5473
+ if (existing.agent !== desired) patch.agent = desired;
5474
+ if (existing.model !== defaults.model) patch.model = defaults.model;
5475
+ if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
5476
+ if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
5477
+ }
5478
+ if (Object.keys(patch).length > 0) {
5479
+ return updateThread(existing.id, patch);
5480
+ }
5481
+ return existing;
5478
5482
  }
5479
- return existing;
5480
5483
  }
5481
- const created = createGlobalChat({
5484
+ return createGlobalChat({
5482
5485
  sourceRef: ref,
5483
5486
  agent: desired,
5484
5487
  model: defaults.model,
5485
5488
  effort: defaults.effort,
5486
5489
  fast: defaults.fast
5487
5490
  });
5488
- const all = listThreads({ includeArchived: true }).filter(
5489
- (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
5490
- ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
5491
- return all[0] ?? created;
5492
5491
  }
5493
5492
  function ensureCloudCoordinator(agent) {
5494
5493
  const defaults = resolveThreadDefaults();
@@ -9460,6 +9459,7 @@ __export(index_exports, {
9460
9459
  findConventionSetup: () => findConventionSetup,
9461
9460
  findInvalidCacheControlTtlOrder: () => findInvalidCacheControlTtlOrder,
9462
9461
  findOrphanWorktrees: () => findOrphanWorktrees,
9462
+ findSlackCoordinator: () => findSlackCoordinator,
9463
9463
  findThreadByRef: () => findThreadByRef,
9464
9464
  findThreadForStackLayer: () => findThreadForStackLayer,
9465
9465
  flattenTurnInput: () => flattenTurnInput,
@@ -13474,6 +13474,7 @@ function createChatTab(input) {
13474
13474
  if (isOrchestratorThread(from) || binding.sourceType === "orchestration") {
13475
13475
  assertOrchestratorCapableAgent(nextAgent);
13476
13476
  }
13477
+ const singletonInbox = isSlackCoordinatorThread(from) || isCloudCoordinatorThread(from);
13477
13478
  const thread = createEmptyThread({
13478
13479
  title,
13479
13480
  // Chat-tab nicknames (soccer team or explicit) must stick. Post-turn
@@ -13481,6 +13482,10 @@ function createChatTab(input) {
13481
13482
  // shared worktree folder name (e.g. fork "Arsenal" → "Monaco").
13482
13483
  userSetTitle: true,
13483
13484
  ...binding,
13485
+ // Slack / Brightsy cloud identity stays on the original chat. A + tab
13486
+ // that copies `slack:team:user` would steal inbound DMs after you close
13487
+ // the connected chat.
13488
+ sourceRef: singletonInbox ? title : binding.sourceRef,
13484
13489
  agent: nextAgent,
13485
13490
  model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
13486
13491
  effort: input.effort !== void 0 ? input.effort : from.effort,
@@ -15734,6 +15739,9 @@ var Orchestrator = class {
15734
15739
  }
15735
15740
  return withThreadLock(thread.id, async () => {
15736
15741
  const current = this.requireThread(thread.id);
15742
+ if (current.status === "archived") {
15743
+ throw new Error(`Thread is archived: ${thread.id}`);
15744
+ }
15737
15745
  const queue = [...current.queue, prompt];
15738
15746
  this.haltDrain.delete(thread.id);
15739
15747
  const patch = { queue, status: "queued" };
@@ -20130,11 +20138,16 @@ function slackInboundSuperseded(opts) {
20130
20138
  }
20131
20139
  return opts.currentInboundGeneration() !== opts.inboundGeneration;
20132
20140
  }
20133
- function interruptSlackCoordinatorForInbound(msg, agent, log = () => void 0) {
20141
+ function slackCoordinatorGone(err) {
20142
+ const errMsg = err instanceof Error ? err.message : String(err);
20143
+ return /thread not found|thread is archived/i.test(errMsg);
20144
+ }
20145
+ function interruptSlackCoordinatorForInbound(msg, _agent, log = () => void 0) {
20134
20146
  const userId = msg.userId?.trim();
20135
20147
  if (!userId) return false;
20136
20148
  try {
20137
- const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
20149
+ const coordinator = findSlackCoordinator(msg.teamId, userId);
20150
+ if (!coordinator) return false;
20138
20151
  const fresh = readThread(coordinator.id) ?? coordinator;
20139
20152
  if (fresh.status !== "running" && fresh.status !== "queued") return false;
20140
20153
  getOrchestrator().stop(fresh.id, { clearQueue: true });
@@ -20300,15 +20313,16 @@ async function handleSlackInbound(msg, opts) {
20300
20313
  log(`skip superseded ${msg.kind} ${msg.ts}`);
20301
20314
  return;
20302
20315
  }
20303
- const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
20304
- let fresh = readThread(coordinator.id) ?? coordinator;
20305
20316
  if (isSlackStopCommand(msg.text)) {
20306
- try {
20307
- getOrchestrator().stop(fresh.id, { clearQueue: true });
20308
- log(`stop ${msg.kind} ${msg.ts} \u2192 coordinator ${fresh.id.slice(0, 8)}`);
20309
- } catch (err) {
20310
- const errMsg = err instanceof Error ? err.message : String(err);
20311
- log(`stop ${msg.ts}: ${errMsg}`);
20317
+ const live = findSlackCoordinator(msg.teamId, userId);
20318
+ if (live) {
20319
+ try {
20320
+ getOrchestrator().stop(live.id, { clearQueue: true });
20321
+ log(`stop ${msg.kind} ${msg.ts} \u2192 coordinator ${live.id.slice(0, 8)}`);
20322
+ } catch (err) {
20323
+ const errMsg = err instanceof Error ? err.message : String(err);
20324
+ log(`stop ${msg.ts}: ${errMsg}`);
20325
+ }
20312
20326
  }
20313
20327
  if (slackInboundSuperseded(opts)) {
20314
20328
  log(`skip superseded stop reply ${msg.ts}`);
@@ -20318,34 +20332,65 @@ async function handleSlackInbound(msg, opts) {
20318
20332
  log(`replied stopped ${msg.ts}`);
20319
20333
  return;
20320
20334
  }
20335
+ const opened = ensureSlackCoordinator(msg.teamId, userId, agent);
20336
+ let fresh = readThread(opened.id) ?? opened;
20321
20337
  if (fresh.status === "running" || fresh.status === "queued") {
20322
20338
  interruptSlackCoordinatorForInbound(msg, agent, log);
20323
- fresh = readThread(coordinator.id) ?? coordinator;
20339
+ fresh = readThread(fresh.id) ?? fresh;
20324
20340
  }
20325
20341
  log(
20326
20342
  `run ${msg.kind} ${msg.ts} user ${userId} \u2192 coordinator ${fresh.id.slice(0, 8)} (${inventory.length} workspace${inventory.length === 1 ? "" : "s"})`
20327
20343
  );
20328
20344
  const prompt = formatSlackInboundPrompt(msg);
20329
- setSlackReplyTarget({
20330
- threadId: fresh.id,
20331
- teamId: msg.teamId,
20332
- channelId: msg.channelId,
20333
- threadTs: slackReplyThreadTs(msg)
20334
- });
20335
20345
  const orch = getOrchestrator();
20346
+ const bindReplyTarget = (threadId) => {
20347
+ setSlackReplyTarget({
20348
+ threadId,
20349
+ teamId: msg.teamId,
20350
+ channelId: msg.channelId,
20351
+ threadTs: slackReplyThreadTs(msg)
20352
+ });
20353
+ };
20354
+ bindReplyTarget(fresh.id);
20355
+ const runTurn = async (threadId) => {
20356
+ await orch.send(threadId, prompt);
20357
+ await orch.waitForTurn(threadId, 14 * 60 * 1e3);
20358
+ };
20336
20359
  let reply;
20337
20360
  try {
20338
- await orch.send(fresh.id, prompt);
20339
- await orch.waitForTurn(fresh.id, 14 * 60 * 1e3);
20361
+ try {
20362
+ await runTurn(fresh.id);
20363
+ } catch (err) {
20364
+ if (!slackCoordinatorGone(err)) throw err;
20365
+ log(`coordinator ${fresh.id.slice(0, 8)} gone, opening a new chat`);
20366
+ fresh = ensureSlackCoordinator(msg.teamId, userId, agent, { forceNew: true });
20367
+ bindReplyTarget(fresh.id);
20368
+ await runTurn(fresh.id);
20369
+ }
20340
20370
  if (slackInboundSuperseded(opts)) {
20341
20371
  log(`turn finished ${msg.ts} (superseded)`);
20342
20372
  return;
20343
20373
  }
20344
- const after = readThread(fresh.id);
20345
- if (!after || after.status === "stopped" || after.status === "archived") {
20374
+ let after = readThread(fresh.id);
20375
+ if (after?.status === "stopped") {
20346
20376
  log(`turn finished ${msg.ts} (interrupted, skip post)`);
20347
20377
  return;
20348
20378
  }
20379
+ if (!after || after.status === "archived") {
20380
+ log(`coordinator ${fresh.id.slice(0, 8)} closed, opening a new chat`);
20381
+ fresh = ensureSlackCoordinator(msg.teamId, userId, agent, { forceNew: true });
20382
+ bindReplyTarget(fresh.id);
20383
+ await runTurn(fresh.id);
20384
+ if (slackInboundSuperseded(opts)) {
20385
+ log(`turn finished ${msg.ts} (superseded)`);
20386
+ return;
20387
+ }
20388
+ after = readThread(fresh.id);
20389
+ if (!after || after.status === "stopped" || after.status === "archived") {
20390
+ log(`turn finished ${msg.ts} (interrupted, skip post)`);
20391
+ return;
20392
+ }
20393
+ }
20349
20394
  reply = orch.getTurnResult(fresh.id).text.trim();
20350
20395
  } catch (err) {
20351
20396
  if (slackInboundSuperseded(opts)) {
@@ -20353,8 +20398,7 @@ async function handleSlackInbound(msg, opts) {
20353
20398
  return;
20354
20399
  }
20355
20400
  const errMsg = err instanceof Error ? err.message : String(err);
20356
- const gone = /thread not found/i.test(errMsg);
20357
- if (gone) {
20401
+ if (slackCoordinatorGone(err)) {
20358
20402
  log(`turn finished ${msg.ts} (thread gone, skip post)`);
20359
20403
  return;
20360
20404
  }
@@ -21169,6 +21213,7 @@ async function startSlackRelayServer(opts) {
21169
21213
  findConventionSetup,
21170
21214
  findInvalidCacheControlTtlOrder,
21171
21215
  findOrphanWorktrees,
21216
+ findSlackCoordinator,
21172
21217
  findThreadByRef,
21173
21218
  findThreadForStackLayer,
21174
21219
  flattenTurnInput,
package/dist/index.d.cts CHANGED
@@ -1070,12 +1070,19 @@ declare function listGlobalThreads(includeArchived?: boolean): Thread[];
1070
1070
  /** Stable sourceRef for a Slack inbound orchestration chat (one per Slack user). */
1071
1071
  declare function slackCoordinatorSourceRef(teamId: string, userId: string): string;
1072
1072
  declare function isSlackCoordinatorThread(thread: Pick<Thread, 'sourceType' | 'sourceRef' | 'repoPath'>): boolean;
1073
+ /** Live Slack inbound chat for this Slack user, if any. Does not create. */
1074
+ declare function findSlackCoordinator(teamId: string, userId: string): Thread | undefined;
1073
1075
  /**
1074
1076
  * Find or create a Global orchestration chat for one Slack user (team + user).
1075
1077
  * Inbound DMs/@mentions from that person continue this thread — not the Brightsy
1076
1078
  * cloud singleton and not other Slack users' chats.
1079
+ *
1080
+ * `forceNew` opens a replacement after the previous chat was closed/archived
1081
+ * mid-turn (do not reuse a zombie that send() just rejected).
1077
1082
  */
1078
- declare function ensureSlackCoordinator(teamId: string, userId: string, agent: AgentKind): Thread;
1083
+ declare function ensureSlackCoordinator(teamId: string, userId: string, agent: AgentKind, opts?: {
1084
+ forceNew?: boolean;
1085
+ }): Thread;
1079
1086
  /** Find or create the singleton Brightsy cloud coordinator under Global. */
1080
1087
  declare function ensureCloudCoordinator(agent: AgentKind): Thread;
1081
1088
 
@@ -4268,8 +4275,9 @@ interface SlackListenOptions {
4268
4275
  /**
4269
4276
  * Kill an in-flight Slack coordinator turn so a follow-up can start immediately.
4270
4277
  * Same force-stop as MCP `send_to_thread` (`clearQueue: true`).
4278
+ * Does not create a chat — empty-board inbound is handled in handleSlackInbound.
4271
4279
  */
4272
- declare function interruptSlackCoordinatorForInbound(msg: SlackInboundMessage, agent: AgentKind, log?: (line: string) => void): boolean;
4280
+ declare function interruptSlackCoordinatorForInbound(msg: SlackInboundMessage, _agent: AgentKind, log?: (line: string) => void): boolean;
4273
4281
  declare function formatSlackInboundPrompt(msg: SlackInboundMessage): string;
4274
4282
  /**
4275
4283
  * Prefix Slack replies with This Mac's destination (`Work: …`) so a user with
@@ -4463,4 +4471,4 @@ interface SlackRelayClientOptions {
4463
4471
  */
4464
4472
  declare function runSlackRelayClient(opts: SlackRelayClientOptions): Promise<void>;
4465
4473
 
4466
- export { AGENT_GIT_ACTIONS, ATTACHMENTS_DIR, type ActiveRun, type AddStackLayerInput, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentGitAction, type AgentInstructionFile, type AgentKind, type AgentModelCatalog, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BAKED_SLACK_RELAY_URL, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLAUDE_MODEL_CATALOG, 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, CONVENTION_SETUP_RELPATHS, COORDINATOR_TOOL_PLAYBOOK, type CaffeinateHoldState, type ClaudeHarnessSettings, type CleanupOrphansResult, type CliAgentKind, type CliExecutableSettings, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type ConventionSetupFile, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateStackInput, 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, GITHUB_GIT_AUTH_MODES, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GhStackStatus, type GitHubStatus, type GitWorktreeStatus, type GithubGitAuthMode, HARNESS_ENV_KEYS, type HarnessId, type InitStackFromThreadInput, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, LEGACY_ATTACHMENTS_DIR, LEGACY_PLAN_FILE_REL, LEGACY_REVIEW_REQUEST_PATH, LINEAR_OAUTH_CANCELLED, LINEAR_OAUTH_PORT, LINEAR_OAUTH_REDIRECT, LINEAR_OAUTH_SCOPES, type LandPreview, type LandResult, type LinearComment, type LinearIssue, LinearOAuthCancelledError, type LinearTeam, type LinearTeamsResult, type LinearWorkflowState, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, ORCHESTRATOR_AGENT_KINDS, type OpenPrStackLayersInput, type OpenStackLayerInput, type OpenStackLayerResult, type OrchestrationQuotaOnLimit, Orchestrator, type OrchestratorAgentKind, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PASTE_ATTACH_MIN_CHARS, PASTE_ATTACH_MIN_LINES, PLAN_FILE_NAME, PLAN_FILE_REL, PLAN_MODE_INSTRUCTION, type PendingPlanQuestions, type PlanQuestion, type PlanQuestionAnswer, type PlanQuestionOption, type PlanToolPartLike, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type PrStack, type PrStackLayer, type PresentedPlan, type PublicAppSettings, type PublicIntegrationsSettings, REPO_REVIEW_NAME, REPO_REVIEW_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PATH, REVIEW_REQUEST_PREFILL, REVIEW_REQUEST_TEMPLATE, type RepoSettings, type RepoSetupInfo, type RequestReviewResult, type ResolvedReviewGuidelines, type ReviewGuidelinesSource, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_MCP_PROFILE_ENV, SLACK_LISTEN_STOPPED_REPLY, SLACK_LISTEN_TIMEOUT_REPLY, SLACK_OAUTH_CANCELLED, SLACK_OAUTH_REDIRECT, SLACK_REPLY_FORMATTING, SLACK_SEEN_REACTION, type ScriptHandle, type SetupRunResult, type SideboardMcpProfile, type SkillInfo, type SlackInboundMessage, type SlackListenOptions, type SlackListenStatus, SlackOAuthCancelledError, type SlackOutboundReply, type SlackOutboundWatch, type SlackRelayClientMessage, type SlackRelayClientOptions, SlackRelayHub, type SlackRelayServerHandle, type SlackRelayServerMessage, type SlackRelayServerOptions, type SlackReplyBadge, type SlackWorkspaceInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, THINKING_EFFORTS, type TeamName, type ThinkingEffort, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type ToolPartLike, type TranscriptToolDetail, type TurnCommand, type UsageScope, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, ackSlackInboundSeen, addPrStackLayer, addStackLayerFromThread, addWorkspace, adoptThread, agentGitPrompt, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendIndexedGitConfig, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyGithubGitAuthEnv, applyThreadIntoMain, applyTurnUsage, assertOrchestratorCapableAgent, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, attachmentsGitignoreBody, autoArchiveOnMergeEnabled, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyInjectWorktreeMcpEnabled, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildPastedTextAttachment, buildReviewRequestAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateHoldPath, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, caffeinateWhileSlackListenEnabled, captureLoginEnv, captureTurnBaseline, checkoutPrStackLayer, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, codexSandboxWritableRootsArgs, codexUnattendedGitConfigArgs, coerceOrchestratorAgent, collectTakenTeamSlugs, commentLinearIssue, commitAll, conductorBundledBinDir, conductorDbPath, confirmLand, connectBrightsyTeam, connectSlackToken, contextTokens, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createExistingBranchWorktree, createGlobalChat, createLinearIssue, createLinearPkce, createOrUpdatePr, createPrStack, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectGhStack, detectLocalMergeConflicts, disconnectBrightsyTeam, disconnectLinear, disconnectLinearConnection, disconnectSlackWorkspace, discoverSkills, dismissSlackReplyBadge, dropCachedPrefixOnResume, encodeBrightsyTarget, enrichPathWithNpmGlobalBin, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureReviewRequestFile, ensureSlackCoordinator, ensureSlackDeviceIdentity, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractPendingPlanQuestions, extractPresentedPlan, extractiveSummary, fetchPrHead, finalizeParts, findConventionSetup, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, findThreadForStackLayer, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatFetchError, formatGhLandError, formatGitAuthModeDirective, formatIpcInvokeError, formatMergePrError, formatMessagesAsTranscript, formatPlanQuestionAnswers, formatPlanQuestionsForChat, formatProcessGuideDirective, formatRateLimitResetHint, formatRenameBranchDirective, formatSlackExternalReplyPrompt, formatSlackInboundPrompt, formatSlackRepliesForTurn, formatSlackSignedReply, formatTranscriptMarkdown, formatUiReminder, formatWorkspaceInventory, formatWorktreeDirective, formatWorktreeReminder, fromInclusiveInputUsage, getAdapter, getAgentSetupInfo, getBrightsySession, getCaffeinateHold, getDefaultAgent, getDefaultEffort, getDefaultFast, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getGithubGitAuthMode, getGithubPat, getIssueSource, getLinearApiKey, getLinearAuthToken, getLinearIssue, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrForHeadBranch, getPrMeta, getPrStack, getRepoSetupInfo, getRunMode, getRunScript, getSlackWorkspace, gh, ghHeadRef, ghRepoSelectArgs, git, githubAgentGitEnv, globalAgentCwd, handleSlackInbound, harnessEnvKey, hasBakedLinearOAuth, hasBakedSlackOAuth, hasConductorHook, hasConventionSetup, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, httpFetch, importConductorWorkspace, importConductorWorkspaceAsync, initPrStack, initStackFromThread, initializeGitRepository, inspectGitWorktree, installAgent, interruptSlackCoordinatorForInbound, isAskUserToolName, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isConductorBundledCli, isCursorAutoModel, isDefaultishSourceRef, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isInPrStack, isInboundForThisDesktop, isLinearConnected, isLinearOAuthCancelled, isOrchestratorCapableAgent, isOrchestratorThread, isPidAlive, isPlaceholderBranch, isPrNotMergeableError, isPresentPlanToolName, isSessionQuotaLimit, isSideboardScratchPath, isSlackCoordinatorThread, isSlackExternalReplyPrompt, isSlackOAuthCancelled, isThinkingEffort, isThreadCaffeinated, isWorkspaceScratchPath, linearAuthorizationHeader, linearGraphql, linearOAuthAuthorizeUrl, linearOAuthCredentials, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listLinearTeams, listModelsForAgent, listOpencodeModels, listPrs, listRunScripts, listSlackOutboundWatches, listSlackReplyBadges, listSlackWorkspaces, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergeAgentGitAuthEnv, mergePr, mergePrStack, mergeSideboardIntoMcpServersJson, mergeUsage, nextPastedTextName, nextThinkingEffort, nonInteractiveGitProcessEnv, normalizeParseResult, normalizeThinkingEffort, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, openPrStackLayers, openStackLayer, opencodeAdapter, orchestrationQuotaFallbackAgent, orchestrationQuotaOnLimit, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGhStackViewJson, parseGithubSlugFromRemoteUrl, parseMcpList, parsePlanQuestionsInput, parseSessionQuotaResetAt, parseSlackRelayClientMessage, parseSlackRelayServerMessage, partsToAssistantText, pastedTextStats, pendingSlackExternalReplies, permalinkForSlackReplyBadge, permissionMode, persistVaultKeyInKeychain, planFileAbs, posixShellSingleQuote, prepareTerminalCommand, previewLand, promptMentionsBrightsy, pushBranch, readExistingReviewRequestFile, readKeychainVaultKey, readPlanFile, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, recordSlackOutboundWatch, refreshGitHubAuth, refreshSlackReplyBadges, registerPackagedUserMcpClients, releaseCaffeinateHoldForThread, removeWorkspace, removeWorktree, repoSlug, requestOccupancy, requestReview, requireAgent, resetGhStackDetectCache, resetGithubAgentTokenMemo, resolveAgentExecutable, resolveAgentGitAuthEnv, resolveClaudeExecutable, resolveCodexGitWritableRoots, resolveCommandBinarySync, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGhAuthToken, resolveGithubAgentToken, resolveGithubRepoSlug, resolveLinearState, resolveLinearTeam, resolveLoginCommand, resolveNewThreadOptions, resolvePlanMarkdown, resolvePrSelector, resolvePrSelectors, resolveQuotaFallbackAgent, resolveRepoRoot, resolveReviewGuidelines, resolveSlackListenMode, resolveThreadDefaults, resolveThreadEffort, resolveVaultKey, resolveWorktreeStartPoint, rewriteLinearError, run, runArchiveScript, runCloudConnect, runConventionSetup, runCursorWorktreeSetup, runSetupScript, runSlackListen, runSlackRelayClient, runWorkspaceSetup, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, saveLinearOAuth, scrubGithubTokensFromChildEnv, secureFileUnlocksWith, setCaffeinateHold, setHttpFetchImpl, setStatus, setVaultMasterKey, settingsSourceLabel, shouldAttachPastedText, shouldCompactContext, shouldInjectBrightsyMcp, shouldRefreshReviewRequestTemplate, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardMcpProfile, sideboardReposDir, sideboardWorkspacesDir, slackAppLevelToken, slackArchiveUrl, slackCoordinatorSourceRef, slackListenEnabled, slackOAuthCredentials, slackOAuthResultUrl, slackRelayUrl, slugify, spawnAgentTurn, splitForCompaction, stackAgentDefaultsFrom, stackIdFrom, stackMergeReadiness, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startLinearOAuth, startMcpServer, startOrchestration, startSlackOAuth, startSlackRelayServer, stripBrightsyNdjsonNoise, stripNestedElectronEnv, submitPrStack, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, thinkingEffortBars, thinkingEffortLabel, threadDisplayLabel, threadFilePath, threadLockPath, threadRequestsBrightsyMcp, threadsDir, threadsSharingWorktree, toPublicAppSettings, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAgentExecutable, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateCodexSettings, updateDefaultsSettings, updateIntegrationsSettings, updateLinearIssue, updateOpencodeSettings, updateThread, userClaudeMcpConfigPath, userCursorMcpConfigPath, validateLinearApiKey, warmGithubAgentAuth, withAgentInstructions, withExportedPath, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writePlanFile, writeThread, writeWorktreeFile };
4474
+ export { AGENT_GIT_ACTIONS, ATTACHMENTS_DIR, type ActiveRun, type AddStackLayerInput, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentGitAction, type AgentInstructionFile, type AgentKind, type AgentModelCatalog, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BAKED_SLACK_RELAY_URL, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLAUDE_MODEL_CATALOG, 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, CONVENTION_SETUP_RELPATHS, COORDINATOR_TOOL_PLAYBOOK, type CaffeinateHoldState, type ClaudeHarnessSettings, type CleanupOrphansResult, type CliAgentKind, type CliExecutableSettings, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type ConventionSetupFile, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateStackInput, 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, GITHUB_GIT_AUTH_MODES, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GhStackStatus, type GitHubStatus, type GitWorktreeStatus, type GithubGitAuthMode, HARNESS_ENV_KEYS, type HarnessId, type InitStackFromThreadInput, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, LEGACY_ATTACHMENTS_DIR, LEGACY_PLAN_FILE_REL, LEGACY_REVIEW_REQUEST_PATH, LINEAR_OAUTH_CANCELLED, LINEAR_OAUTH_PORT, LINEAR_OAUTH_REDIRECT, LINEAR_OAUTH_SCOPES, type LandPreview, type LandResult, type LinearComment, type LinearIssue, LinearOAuthCancelledError, type LinearTeam, type LinearTeamsResult, type LinearWorkflowState, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, ORCHESTRATOR_AGENT_KINDS, type OpenPrStackLayersInput, type OpenStackLayerInput, type OpenStackLayerResult, type OrchestrationQuotaOnLimit, Orchestrator, type OrchestratorAgentKind, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PASTE_ATTACH_MIN_CHARS, PASTE_ATTACH_MIN_LINES, PLAN_FILE_NAME, PLAN_FILE_REL, PLAN_MODE_INSTRUCTION, type PendingPlanQuestions, type PlanQuestion, type PlanQuestionAnswer, type PlanQuestionOption, type PlanToolPartLike, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type PrStack, type PrStackLayer, type PresentedPlan, type PublicAppSettings, type PublicIntegrationsSettings, REPO_REVIEW_NAME, REPO_REVIEW_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PATH, REVIEW_REQUEST_PREFILL, REVIEW_REQUEST_TEMPLATE, type RepoSettings, type RepoSetupInfo, type RequestReviewResult, type ResolvedReviewGuidelines, type ReviewGuidelinesSource, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_MCP_PROFILE_ENV, SLACK_LISTEN_STOPPED_REPLY, SLACK_LISTEN_TIMEOUT_REPLY, SLACK_OAUTH_CANCELLED, SLACK_OAUTH_REDIRECT, SLACK_REPLY_FORMATTING, SLACK_SEEN_REACTION, type ScriptHandle, type SetupRunResult, type SideboardMcpProfile, type SkillInfo, type SlackInboundMessage, type SlackListenOptions, type SlackListenStatus, SlackOAuthCancelledError, type SlackOutboundReply, type SlackOutboundWatch, type SlackRelayClientMessage, type SlackRelayClientOptions, SlackRelayHub, type SlackRelayServerHandle, type SlackRelayServerMessage, type SlackRelayServerOptions, type SlackReplyBadge, type SlackWorkspaceInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, THINKING_EFFORTS, type TeamName, type ThinkingEffort, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type ToolPartLike, type TranscriptToolDetail, type TurnCommand, type UsageScope, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, ackSlackInboundSeen, addPrStackLayer, addStackLayerFromThread, addWorkspace, adoptThread, agentGitPrompt, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendIndexedGitConfig, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyGithubGitAuthEnv, applyThreadIntoMain, applyTurnUsage, assertOrchestratorCapableAgent, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, attachmentsGitignoreBody, autoArchiveOnMergeEnabled, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyInjectWorktreeMcpEnabled, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildPastedTextAttachment, buildReviewRequestAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateHoldPath, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, caffeinateWhileSlackListenEnabled, captureLoginEnv, captureTurnBaseline, checkoutPrStackLayer, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, codexSandboxWritableRootsArgs, codexUnattendedGitConfigArgs, coerceOrchestratorAgent, collectTakenTeamSlugs, commentLinearIssue, commitAll, conductorBundledBinDir, conductorDbPath, confirmLand, connectBrightsyTeam, connectSlackToken, contextTokens, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createExistingBranchWorktree, createGlobalChat, createLinearIssue, createLinearPkce, createOrUpdatePr, createPrStack, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectGhStack, detectLocalMergeConflicts, disconnectBrightsyTeam, disconnectLinear, disconnectLinearConnection, disconnectSlackWorkspace, discoverSkills, dismissSlackReplyBadge, dropCachedPrefixOnResume, encodeBrightsyTarget, enrichPathWithNpmGlobalBin, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureReviewRequestFile, ensureSlackCoordinator, ensureSlackDeviceIdentity, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractPendingPlanQuestions, extractPresentedPlan, extractiveSummary, fetchPrHead, finalizeParts, findConventionSetup, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findSlackCoordinator, findThreadByRef, findThreadForStackLayer, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatFetchError, formatGhLandError, formatGitAuthModeDirective, formatIpcInvokeError, formatMergePrError, formatMessagesAsTranscript, formatPlanQuestionAnswers, formatPlanQuestionsForChat, formatProcessGuideDirective, formatRateLimitResetHint, formatRenameBranchDirective, formatSlackExternalReplyPrompt, formatSlackInboundPrompt, formatSlackRepliesForTurn, formatSlackSignedReply, formatTranscriptMarkdown, formatUiReminder, formatWorkspaceInventory, formatWorktreeDirective, formatWorktreeReminder, fromInclusiveInputUsage, getAdapter, getAgentSetupInfo, getBrightsySession, getCaffeinateHold, getDefaultAgent, getDefaultEffort, getDefaultFast, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getGithubGitAuthMode, getGithubPat, getIssueSource, getLinearApiKey, getLinearAuthToken, getLinearIssue, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrForHeadBranch, getPrMeta, getPrStack, getRepoSetupInfo, getRunMode, getRunScript, getSlackWorkspace, gh, ghHeadRef, ghRepoSelectArgs, git, githubAgentGitEnv, globalAgentCwd, handleSlackInbound, harnessEnvKey, hasBakedLinearOAuth, hasBakedSlackOAuth, hasConductorHook, hasConventionSetup, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, httpFetch, importConductorWorkspace, importConductorWorkspaceAsync, initPrStack, initStackFromThread, initializeGitRepository, inspectGitWorktree, installAgent, interruptSlackCoordinatorForInbound, isAskUserToolName, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isConductorBundledCli, isCursorAutoModel, isDefaultishSourceRef, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isInPrStack, isInboundForThisDesktop, isLinearConnected, isLinearOAuthCancelled, isOrchestratorCapableAgent, isOrchestratorThread, isPidAlive, isPlaceholderBranch, isPrNotMergeableError, isPresentPlanToolName, isSessionQuotaLimit, isSideboardScratchPath, isSlackCoordinatorThread, isSlackExternalReplyPrompt, isSlackOAuthCancelled, isThinkingEffort, isThreadCaffeinated, isWorkspaceScratchPath, linearAuthorizationHeader, linearGraphql, linearOAuthAuthorizeUrl, linearOAuthCredentials, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listLinearTeams, listModelsForAgent, listOpencodeModels, listPrs, listRunScripts, listSlackOutboundWatches, listSlackReplyBadges, listSlackWorkspaces, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergeAgentGitAuthEnv, mergePr, mergePrStack, mergeSideboardIntoMcpServersJson, mergeUsage, nextPastedTextName, nextThinkingEffort, nonInteractiveGitProcessEnv, normalizeParseResult, normalizeThinkingEffort, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, openPrStackLayers, openStackLayer, opencodeAdapter, orchestrationQuotaFallbackAgent, orchestrationQuotaOnLimit, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGhStackViewJson, parseGithubSlugFromRemoteUrl, parseMcpList, parsePlanQuestionsInput, parseSessionQuotaResetAt, parseSlackRelayClientMessage, parseSlackRelayServerMessage, partsToAssistantText, pastedTextStats, pendingSlackExternalReplies, permalinkForSlackReplyBadge, permissionMode, persistVaultKeyInKeychain, planFileAbs, posixShellSingleQuote, prepareTerminalCommand, previewLand, promptMentionsBrightsy, pushBranch, readExistingReviewRequestFile, readKeychainVaultKey, readPlanFile, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, recordSlackOutboundWatch, refreshGitHubAuth, refreshSlackReplyBadges, registerPackagedUserMcpClients, releaseCaffeinateHoldForThread, removeWorkspace, removeWorktree, repoSlug, requestOccupancy, requestReview, requireAgent, resetGhStackDetectCache, resetGithubAgentTokenMemo, resolveAgentExecutable, resolveAgentGitAuthEnv, resolveClaudeExecutable, resolveCodexGitWritableRoots, resolveCommandBinarySync, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGhAuthToken, resolveGithubAgentToken, resolveGithubRepoSlug, resolveLinearState, resolveLinearTeam, resolveLoginCommand, resolveNewThreadOptions, resolvePlanMarkdown, resolvePrSelector, resolvePrSelectors, resolveQuotaFallbackAgent, resolveRepoRoot, resolveReviewGuidelines, resolveSlackListenMode, resolveThreadDefaults, resolveThreadEffort, resolveVaultKey, resolveWorktreeStartPoint, rewriteLinearError, run, runArchiveScript, runCloudConnect, runConventionSetup, runCursorWorktreeSetup, runSetupScript, runSlackListen, runSlackRelayClient, runWorkspaceSetup, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, saveLinearOAuth, scrubGithubTokensFromChildEnv, secureFileUnlocksWith, setCaffeinateHold, setHttpFetchImpl, setStatus, setVaultMasterKey, settingsSourceLabel, shouldAttachPastedText, shouldCompactContext, shouldInjectBrightsyMcp, shouldRefreshReviewRequestTemplate, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardMcpProfile, sideboardReposDir, sideboardWorkspacesDir, slackAppLevelToken, slackArchiveUrl, slackCoordinatorSourceRef, slackListenEnabled, slackOAuthCredentials, slackOAuthResultUrl, slackRelayUrl, slugify, spawnAgentTurn, splitForCompaction, stackAgentDefaultsFrom, stackIdFrom, stackMergeReadiness, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startLinearOAuth, startMcpServer, startOrchestration, startSlackOAuth, startSlackRelayServer, stripBrightsyNdjsonNoise, stripNestedElectronEnv, submitPrStack, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, thinkingEffortBars, thinkingEffortLabel, threadDisplayLabel, threadFilePath, threadLockPath, threadRequestsBrightsyMcp, threadsDir, threadsSharingWorktree, toPublicAppSettings, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAgentExecutable, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateCodexSettings, updateDefaultsSettings, updateIntegrationsSettings, updateLinearIssue, updateOpencodeSettings, updateThread, userClaudeMcpConfigPath, userCursorMcpConfigPath, validateLinearApiKey, warmGithubAgentAuth, withAgentInstructions, withExportedPath, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writePlanFile, writeThread, writeWorktreeFile };
package/dist/index.d.ts CHANGED
@@ -1070,12 +1070,19 @@ declare function listGlobalThreads(includeArchived?: boolean): Thread[];
1070
1070
  /** Stable sourceRef for a Slack inbound orchestration chat (one per Slack user). */
1071
1071
  declare function slackCoordinatorSourceRef(teamId: string, userId: string): string;
1072
1072
  declare function isSlackCoordinatorThread(thread: Pick<Thread, 'sourceType' | 'sourceRef' | 'repoPath'>): boolean;
1073
+ /** Live Slack inbound chat for this Slack user, if any. Does not create. */
1074
+ declare function findSlackCoordinator(teamId: string, userId: string): Thread | undefined;
1073
1075
  /**
1074
1076
  * Find or create a Global orchestration chat for one Slack user (team + user).
1075
1077
  * Inbound DMs/@mentions from that person continue this thread — not the Brightsy
1076
1078
  * cloud singleton and not other Slack users' chats.
1079
+ *
1080
+ * `forceNew` opens a replacement after the previous chat was closed/archived
1081
+ * mid-turn (do not reuse a zombie that send() just rejected).
1077
1082
  */
1078
- declare function ensureSlackCoordinator(teamId: string, userId: string, agent: AgentKind): Thread;
1083
+ declare function ensureSlackCoordinator(teamId: string, userId: string, agent: AgentKind, opts?: {
1084
+ forceNew?: boolean;
1085
+ }): Thread;
1079
1086
  /** Find or create the singleton Brightsy cloud coordinator under Global. */
1080
1087
  declare function ensureCloudCoordinator(agent: AgentKind): Thread;
1081
1088
 
@@ -4268,8 +4275,9 @@ interface SlackListenOptions {
4268
4275
  /**
4269
4276
  * Kill an in-flight Slack coordinator turn so a follow-up can start immediately.
4270
4277
  * Same force-stop as MCP `send_to_thread` (`clearQueue: true`).
4278
+ * Does not create a chat — empty-board inbound is handled in handleSlackInbound.
4271
4279
  */
4272
- declare function interruptSlackCoordinatorForInbound(msg: SlackInboundMessage, agent: AgentKind, log?: (line: string) => void): boolean;
4280
+ declare function interruptSlackCoordinatorForInbound(msg: SlackInboundMessage, _agent: AgentKind, log?: (line: string) => void): boolean;
4273
4281
  declare function formatSlackInboundPrompt(msg: SlackInboundMessage): string;
4274
4282
  /**
4275
4283
  * Prefix Slack replies with This Mac's destination (`Work: …`) so a user with
@@ -4463,4 +4471,4 @@ interface SlackRelayClientOptions {
4463
4471
  */
4464
4472
  declare function runSlackRelayClient(opts: SlackRelayClientOptions): Promise<void>;
4465
4473
 
4466
- export { AGENT_GIT_ACTIONS, ATTACHMENTS_DIR, type ActiveRun, type AddStackLayerInput, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentGitAction, type AgentInstructionFile, type AgentKind, type AgentModelCatalog, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BAKED_SLACK_RELAY_URL, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLAUDE_MODEL_CATALOG, 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, CONVENTION_SETUP_RELPATHS, COORDINATOR_TOOL_PLAYBOOK, type CaffeinateHoldState, type ClaudeHarnessSettings, type CleanupOrphansResult, type CliAgentKind, type CliExecutableSettings, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type ConventionSetupFile, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateStackInput, 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, GITHUB_GIT_AUTH_MODES, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GhStackStatus, type GitHubStatus, type GitWorktreeStatus, type GithubGitAuthMode, HARNESS_ENV_KEYS, type HarnessId, type InitStackFromThreadInput, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, LEGACY_ATTACHMENTS_DIR, LEGACY_PLAN_FILE_REL, LEGACY_REVIEW_REQUEST_PATH, LINEAR_OAUTH_CANCELLED, LINEAR_OAUTH_PORT, LINEAR_OAUTH_REDIRECT, LINEAR_OAUTH_SCOPES, type LandPreview, type LandResult, type LinearComment, type LinearIssue, LinearOAuthCancelledError, type LinearTeam, type LinearTeamsResult, type LinearWorkflowState, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, ORCHESTRATOR_AGENT_KINDS, type OpenPrStackLayersInput, type OpenStackLayerInput, type OpenStackLayerResult, type OrchestrationQuotaOnLimit, Orchestrator, type OrchestratorAgentKind, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PASTE_ATTACH_MIN_CHARS, PASTE_ATTACH_MIN_LINES, PLAN_FILE_NAME, PLAN_FILE_REL, PLAN_MODE_INSTRUCTION, type PendingPlanQuestions, type PlanQuestion, type PlanQuestionAnswer, type PlanQuestionOption, type PlanToolPartLike, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type PrStack, type PrStackLayer, type PresentedPlan, type PublicAppSettings, type PublicIntegrationsSettings, REPO_REVIEW_NAME, REPO_REVIEW_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PATH, REVIEW_REQUEST_PREFILL, REVIEW_REQUEST_TEMPLATE, type RepoSettings, type RepoSetupInfo, type RequestReviewResult, type ResolvedReviewGuidelines, type ReviewGuidelinesSource, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_MCP_PROFILE_ENV, SLACK_LISTEN_STOPPED_REPLY, SLACK_LISTEN_TIMEOUT_REPLY, SLACK_OAUTH_CANCELLED, SLACK_OAUTH_REDIRECT, SLACK_REPLY_FORMATTING, SLACK_SEEN_REACTION, type ScriptHandle, type SetupRunResult, type SideboardMcpProfile, type SkillInfo, type SlackInboundMessage, type SlackListenOptions, type SlackListenStatus, SlackOAuthCancelledError, type SlackOutboundReply, type SlackOutboundWatch, type SlackRelayClientMessage, type SlackRelayClientOptions, SlackRelayHub, type SlackRelayServerHandle, type SlackRelayServerMessage, type SlackRelayServerOptions, type SlackReplyBadge, type SlackWorkspaceInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, THINKING_EFFORTS, type TeamName, type ThinkingEffort, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type ToolPartLike, type TranscriptToolDetail, type TurnCommand, type UsageScope, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, ackSlackInboundSeen, addPrStackLayer, addStackLayerFromThread, addWorkspace, adoptThread, agentGitPrompt, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendIndexedGitConfig, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyGithubGitAuthEnv, applyThreadIntoMain, applyTurnUsage, assertOrchestratorCapableAgent, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, attachmentsGitignoreBody, autoArchiveOnMergeEnabled, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyInjectWorktreeMcpEnabled, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildPastedTextAttachment, buildReviewRequestAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateHoldPath, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, caffeinateWhileSlackListenEnabled, captureLoginEnv, captureTurnBaseline, checkoutPrStackLayer, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, codexSandboxWritableRootsArgs, codexUnattendedGitConfigArgs, coerceOrchestratorAgent, collectTakenTeamSlugs, commentLinearIssue, commitAll, conductorBundledBinDir, conductorDbPath, confirmLand, connectBrightsyTeam, connectSlackToken, contextTokens, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createExistingBranchWorktree, createGlobalChat, createLinearIssue, createLinearPkce, createOrUpdatePr, createPrStack, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectGhStack, detectLocalMergeConflicts, disconnectBrightsyTeam, disconnectLinear, disconnectLinearConnection, disconnectSlackWorkspace, discoverSkills, dismissSlackReplyBadge, dropCachedPrefixOnResume, encodeBrightsyTarget, enrichPathWithNpmGlobalBin, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureReviewRequestFile, ensureSlackCoordinator, ensureSlackDeviceIdentity, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractPendingPlanQuestions, extractPresentedPlan, extractiveSummary, fetchPrHead, finalizeParts, findConventionSetup, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, findThreadForStackLayer, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatFetchError, formatGhLandError, formatGitAuthModeDirective, formatIpcInvokeError, formatMergePrError, formatMessagesAsTranscript, formatPlanQuestionAnswers, formatPlanQuestionsForChat, formatProcessGuideDirective, formatRateLimitResetHint, formatRenameBranchDirective, formatSlackExternalReplyPrompt, formatSlackInboundPrompt, formatSlackRepliesForTurn, formatSlackSignedReply, formatTranscriptMarkdown, formatUiReminder, formatWorkspaceInventory, formatWorktreeDirective, formatWorktreeReminder, fromInclusiveInputUsage, getAdapter, getAgentSetupInfo, getBrightsySession, getCaffeinateHold, getDefaultAgent, getDefaultEffort, getDefaultFast, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getGithubGitAuthMode, getGithubPat, getIssueSource, getLinearApiKey, getLinearAuthToken, getLinearIssue, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrForHeadBranch, getPrMeta, getPrStack, getRepoSetupInfo, getRunMode, getRunScript, getSlackWorkspace, gh, ghHeadRef, ghRepoSelectArgs, git, githubAgentGitEnv, globalAgentCwd, handleSlackInbound, harnessEnvKey, hasBakedLinearOAuth, hasBakedSlackOAuth, hasConductorHook, hasConventionSetup, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, httpFetch, importConductorWorkspace, importConductorWorkspaceAsync, initPrStack, initStackFromThread, initializeGitRepository, inspectGitWorktree, installAgent, interruptSlackCoordinatorForInbound, isAskUserToolName, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isConductorBundledCli, isCursorAutoModel, isDefaultishSourceRef, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isInPrStack, isInboundForThisDesktop, isLinearConnected, isLinearOAuthCancelled, isOrchestratorCapableAgent, isOrchestratorThread, isPidAlive, isPlaceholderBranch, isPrNotMergeableError, isPresentPlanToolName, isSessionQuotaLimit, isSideboardScratchPath, isSlackCoordinatorThread, isSlackExternalReplyPrompt, isSlackOAuthCancelled, isThinkingEffort, isThreadCaffeinated, isWorkspaceScratchPath, linearAuthorizationHeader, linearGraphql, linearOAuthAuthorizeUrl, linearOAuthCredentials, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listLinearTeams, listModelsForAgent, listOpencodeModels, listPrs, listRunScripts, listSlackOutboundWatches, listSlackReplyBadges, listSlackWorkspaces, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergeAgentGitAuthEnv, mergePr, mergePrStack, mergeSideboardIntoMcpServersJson, mergeUsage, nextPastedTextName, nextThinkingEffort, nonInteractiveGitProcessEnv, normalizeParseResult, normalizeThinkingEffort, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, openPrStackLayers, openStackLayer, opencodeAdapter, orchestrationQuotaFallbackAgent, orchestrationQuotaOnLimit, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGhStackViewJson, parseGithubSlugFromRemoteUrl, parseMcpList, parsePlanQuestionsInput, parseSessionQuotaResetAt, parseSlackRelayClientMessage, parseSlackRelayServerMessage, partsToAssistantText, pastedTextStats, pendingSlackExternalReplies, permalinkForSlackReplyBadge, permissionMode, persistVaultKeyInKeychain, planFileAbs, posixShellSingleQuote, prepareTerminalCommand, previewLand, promptMentionsBrightsy, pushBranch, readExistingReviewRequestFile, readKeychainVaultKey, readPlanFile, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, recordSlackOutboundWatch, refreshGitHubAuth, refreshSlackReplyBadges, registerPackagedUserMcpClients, releaseCaffeinateHoldForThread, removeWorkspace, removeWorktree, repoSlug, requestOccupancy, requestReview, requireAgent, resetGhStackDetectCache, resetGithubAgentTokenMemo, resolveAgentExecutable, resolveAgentGitAuthEnv, resolveClaudeExecutable, resolveCodexGitWritableRoots, resolveCommandBinarySync, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGhAuthToken, resolveGithubAgentToken, resolveGithubRepoSlug, resolveLinearState, resolveLinearTeam, resolveLoginCommand, resolveNewThreadOptions, resolvePlanMarkdown, resolvePrSelector, resolvePrSelectors, resolveQuotaFallbackAgent, resolveRepoRoot, resolveReviewGuidelines, resolveSlackListenMode, resolveThreadDefaults, resolveThreadEffort, resolveVaultKey, resolveWorktreeStartPoint, rewriteLinearError, run, runArchiveScript, runCloudConnect, runConventionSetup, runCursorWorktreeSetup, runSetupScript, runSlackListen, runSlackRelayClient, runWorkspaceSetup, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, saveLinearOAuth, scrubGithubTokensFromChildEnv, secureFileUnlocksWith, setCaffeinateHold, setHttpFetchImpl, setStatus, setVaultMasterKey, settingsSourceLabel, shouldAttachPastedText, shouldCompactContext, shouldInjectBrightsyMcp, shouldRefreshReviewRequestTemplate, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardMcpProfile, sideboardReposDir, sideboardWorkspacesDir, slackAppLevelToken, slackArchiveUrl, slackCoordinatorSourceRef, slackListenEnabled, slackOAuthCredentials, slackOAuthResultUrl, slackRelayUrl, slugify, spawnAgentTurn, splitForCompaction, stackAgentDefaultsFrom, stackIdFrom, stackMergeReadiness, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startLinearOAuth, startMcpServer, startOrchestration, startSlackOAuth, startSlackRelayServer, stripBrightsyNdjsonNoise, stripNestedElectronEnv, submitPrStack, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, thinkingEffortBars, thinkingEffortLabel, threadDisplayLabel, threadFilePath, threadLockPath, threadRequestsBrightsyMcp, threadsDir, threadsSharingWorktree, toPublicAppSettings, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAgentExecutable, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateCodexSettings, updateDefaultsSettings, updateIntegrationsSettings, updateLinearIssue, updateOpencodeSettings, updateThread, userClaudeMcpConfigPath, userCursorMcpConfigPath, validateLinearApiKey, warmGithubAgentAuth, withAgentInstructions, withExportedPath, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writePlanFile, writeThread, writeWorktreeFile };
4474
+ export { AGENT_GIT_ACTIONS, ATTACHMENTS_DIR, type ActiveRun, type AddStackLayerInput, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentGitAction, type AgentInstructionFile, type AgentKind, type AgentModelCatalog, type AgentModelInfo, type AgentSetupActionResult, type AgentSetupInfo, type AgentSetupKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BAKED_SLACK_RELAY_URL, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLAUDE_MODEL_CATALOG, 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, CONVENTION_SETUP_RELPATHS, COORDINATOR_TOOL_PLAYBOOK, type CaffeinateHoldState, type ClaudeHarnessSettings, type CleanupOrphansResult, type CliAgentKind, type CliExecutableSettings, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ComposerFileBuffer, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type ConventionSetupFile, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateStackInput, 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, GITHUB_GIT_AUTH_MODES, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GhStackStatus, type GitHubStatus, type GitWorktreeStatus, type GithubGitAuthMode, HARNESS_ENV_KEYS, type HarnessId, type InitStackFromThreadInput, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, LEGACY_ATTACHMENTS_DIR, LEGACY_PLAN_FILE_REL, LEGACY_REVIEW_REQUEST_PATH, LINEAR_OAUTH_CANCELLED, LINEAR_OAUTH_PORT, LINEAR_OAUTH_REDIRECT, LINEAR_OAUTH_SCOPES, type LandPreview, type LandResult, type LinearComment, type LinearIssue, LinearOAuthCancelledError, type LinearTeam, type LinearTeamsResult, type LinearWorkflowState, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, ORCHESTRATOR_AGENT_KINDS, type OpenPrStackLayersInput, type OpenStackLayerInput, type OpenStackLayerResult, type OrchestrationQuotaOnLimit, Orchestrator, type OrchestratorAgentKind, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PASTE_ATTACH_MIN_CHARS, PASTE_ATTACH_MIN_LINES, PLAN_FILE_NAME, PLAN_FILE_REL, PLAN_MODE_INSTRUCTION, type PendingPlanQuestions, type PlanQuestion, type PlanQuestionAnswer, type PlanQuestionOption, type PlanToolPartLike, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type PrStack, type PrStackLayer, type PresentedPlan, type PublicAppSettings, type PublicIntegrationsSettings, REPO_REVIEW_NAME, REPO_REVIEW_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PATH, REVIEW_REQUEST_PREFILL, REVIEW_REQUEST_TEMPLATE, type RepoSettings, type RepoSetupInfo, type RequestReviewResult, type ResolvedReviewGuidelines, type ReviewGuidelinesSource, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_MCP_PROFILE_ENV, SLACK_LISTEN_STOPPED_REPLY, SLACK_LISTEN_TIMEOUT_REPLY, SLACK_OAUTH_CANCELLED, SLACK_OAUTH_REDIRECT, SLACK_REPLY_FORMATTING, SLACK_SEEN_REACTION, type ScriptHandle, type SetupRunResult, type SideboardMcpProfile, type SkillInfo, type SlackInboundMessage, type SlackListenOptions, type SlackListenStatus, SlackOAuthCancelledError, type SlackOutboundReply, type SlackOutboundWatch, type SlackRelayClientMessage, type SlackRelayClientOptions, SlackRelayHub, type SlackRelayServerHandle, type SlackRelayServerMessage, type SlackRelayServerOptions, type SlackReplyBadge, type SlackWorkspaceInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, THINKING_EFFORTS, type TeamName, type ThinkingEffort, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type ToolPartLike, type TranscriptToolDetail, type TurnCommand, type UsageScope, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, ackSlackInboundSeen, addPrStackLayer, addStackLayerFromThread, addWorkspace, adoptThread, agentGitPrompt, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendIndexedGitConfig, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyGithubGitAuthEnv, applyThreadIntoMain, applyTurnUsage, assertOrchestratorCapableAgent, attachmentFromAbsolutePath, attachmentsFromBuffers, attachmentsFromWorktreePaths, attachmentsGitignoreBody, autoArchiveOnMergeEnabled, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyInjectWorktreeMcpEnabled, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildPastedTextAttachment, buildReviewRequestAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateHoldPath, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, caffeinateWhileSlackListenEnabled, captureLoginEnv, captureTurnBaseline, checkoutPrStackLayer, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, codexSandboxWritableRootsArgs, codexUnattendedGitConfigArgs, coerceOrchestratorAgent, collectTakenTeamSlugs, commentLinearIssue, commitAll, conductorBundledBinDir, conductorDbPath, confirmLand, connectBrightsyTeam, connectSlackToken, contextTokens, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createExistingBranchWorktree, createGlobalChat, createLinearIssue, createLinearPkce, createOrUpdatePr, createPrStack, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectGhStack, detectLocalMergeConflicts, disconnectBrightsyTeam, disconnectLinear, disconnectLinearConnection, disconnectSlackWorkspace, discoverSkills, dismissSlackReplyBadge, dropCachedPrefixOnResume, encodeBrightsyTarget, enrichPathWithNpmGlobalBin, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureReviewRequestFile, ensureSlackCoordinator, ensureSlackDeviceIdentity, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractPendingPlanQuestions, extractPresentedPlan, extractiveSummary, fetchPrHead, finalizeParts, findConventionSetup, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findSlackCoordinator, findThreadByRef, findThreadForStackLayer, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatFetchError, formatGhLandError, formatGitAuthModeDirective, formatIpcInvokeError, formatMergePrError, formatMessagesAsTranscript, formatPlanQuestionAnswers, formatPlanQuestionsForChat, formatProcessGuideDirective, formatRateLimitResetHint, formatRenameBranchDirective, formatSlackExternalReplyPrompt, formatSlackInboundPrompt, formatSlackRepliesForTurn, formatSlackSignedReply, formatTranscriptMarkdown, formatUiReminder, formatWorkspaceInventory, formatWorktreeDirective, formatWorktreeReminder, fromInclusiveInputUsage, getAdapter, getAgentSetupInfo, getBrightsySession, getCaffeinateHold, getDefaultAgent, getDefaultEffort, getDefaultFast, getDefaultModel, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getGithubGitAuthMode, getGithubPat, getIssueSource, getLinearApiKey, getLinearAuthToken, getLinearIssue, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrForHeadBranch, getPrMeta, getPrStack, getRepoSetupInfo, getRunMode, getRunScript, getSlackWorkspace, gh, ghHeadRef, ghRepoSelectArgs, git, githubAgentGitEnv, globalAgentCwd, handleSlackInbound, harnessEnvKey, hasBakedLinearOAuth, hasBakedSlackOAuth, hasConductorHook, hasConventionSetup, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, httpFetch, importConductorWorkspace, importConductorWorkspaceAsync, initPrStack, initStackFromThread, initializeGitRepository, inspectGitWorktree, installAgent, interruptSlackCoordinatorForInbound, isAskUserToolName, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isConductorBundledCli, isCursorAutoModel, isDefaultishSourceRef, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isImageFilePath, isInPrStack, isInboundForThisDesktop, isLinearConnected, isLinearOAuthCancelled, isOrchestratorCapableAgent, isOrchestratorThread, isPidAlive, isPlaceholderBranch, isPrNotMergeableError, isPresentPlanToolName, isSessionQuotaLimit, isSideboardScratchPath, isSlackCoordinatorThread, isSlackExternalReplyPrompt, isSlackOAuthCancelled, isThinkingEffort, isThreadCaffeinated, isWorkspaceScratchPath, linearAuthorizationHeader, linearGraphql, linearOAuthAuthorizeUrl, linearOAuthCredentials, listAgentSetupInfo, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listCodexModels, listConductorWorkspaces, listConnectedBrightsyTeams, listCursorModels, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listLinearTeams, listModelsForAgent, listOpencodeModels, listPrs, listRunScripts, listSlackOutboundWatches, listSlackReplyBadges, listSlackWorkspaces, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, loginAgent, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergeAgentGitAuthEnv, mergePr, mergePrStack, mergeSideboardIntoMcpServersJson, mergeUsage, nextPastedTextName, nextThinkingEffort, nonInteractiveGitProcessEnv, normalizeParseResult, normalizeThinkingEffort, normalizeThread, normalizeTurnInput, normalizeWorktreePath, openInSystemTerminal, openPrStackLayers, openStackLayer, opencodeAdapter, orchestrationQuotaFallbackAgent, orchestrationQuotaOnLimit, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGhStackViewJson, parseGithubSlugFromRemoteUrl, parseMcpList, parsePlanQuestionsInput, parseSessionQuotaResetAt, parseSlackRelayClientMessage, parseSlackRelayServerMessage, partsToAssistantText, pastedTextStats, pendingSlackExternalReplies, permalinkForSlackReplyBadge, permissionMode, persistVaultKeyInKeychain, planFileAbs, posixShellSingleQuote, prepareTerminalCommand, previewLand, promptMentionsBrightsy, pushBranch, readExistingReviewRequestFile, readKeychainVaultKey, readPlanFile, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, recordSlackOutboundWatch, refreshGitHubAuth, refreshSlackReplyBadges, registerPackagedUserMcpClients, releaseCaffeinateHoldForThread, removeWorkspace, removeWorktree, repoSlug, requestOccupancy, requestReview, requireAgent, resetGhStackDetectCache, resetGithubAgentTokenMemo, resolveAgentExecutable, resolveAgentGitAuthEnv, resolveClaudeExecutable, resolveCodexGitWritableRoots, resolveCommandBinarySync, resolveConductorCursorAgentId, resolveCursorModelId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGhAuthToken, resolveGithubAgentToken, resolveGithubRepoSlug, resolveLinearState, resolveLinearTeam, resolveLoginCommand, resolveNewThreadOptions, resolvePlanMarkdown, resolvePrSelector, resolvePrSelectors, resolveQuotaFallbackAgent, resolveRepoRoot, resolveReviewGuidelines, resolveSlackListenMode, resolveThreadDefaults, resolveThreadEffort, resolveVaultKey, resolveWorktreeStartPoint, rewriteLinearError, run, runArchiveScript, runCloudConnect, runConventionSetup, runCursorWorktreeSetup, runSetupScript, runSlackListen, runSlackRelayClient, runWorkspaceSetup, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, saveLinearOAuth, scrubGithubTokensFromChildEnv, secureFileUnlocksWith, setCaffeinateHold, setHttpFetchImpl, setStatus, setVaultMasterKey, settingsSourceLabel, shouldAttachPastedText, shouldCompactContext, shouldInjectBrightsyMcp, shouldRefreshReviewRequestTemplate, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardMcpProfile, sideboardReposDir, sideboardWorkspacesDir, slackAppLevelToken, slackArchiveUrl, slackCoordinatorSourceRef, slackListenEnabled, slackOAuthCredentials, slackOAuthResultUrl, slackRelayUrl, slugify, spawnAgentTurn, splitForCompaction, stackAgentDefaultsFrom, stackIdFrom, stackMergeReadiness, stageAbsolutePathsAsAttachments, stageBuffersAsAttachments, startDevServer, startLinearOAuth, startMcpServer, startOrchestration, startSlackOAuth, startSlackRelayServer, stripBrightsyNdjsonNoise, stripNestedElectronEnv, submitPrStack, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, thinkingEffortBars, thinkingEffortLabel, threadDisplayLabel, threadFilePath, threadLockPath, threadRequestsBrightsyMcp, threadsDir, threadsSharingWorktree, toPublicAppSettings, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAgentExecutable, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateCodexSettings, updateDefaultsSettings, updateIntegrationsSettings, updateLinearIssue, updateOpencodeSettings, updateThread, userClaudeMcpConfigPath, userCursorMcpConfigPath, validateLinearApiKey, warmGithubAgentAuth, withAgentInstructions, withExportedPath, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writePlanFile, writeThread, writeWorktreeFile };
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-QKYO6BHB.js";
7
+ } from "./chunk-UYQYK2RY.js";
8
8
  import {
9
9
  BRIGHTSY_MCP_ALLOWED_TOOLS,
10
10
  CLAUDE_MODEL_CATALOG,
@@ -65,7 +65,7 @@ import {
65
65
  threadRequestsBrightsyMcp,
66
66
  totalTokens,
67
67
  writeInjectedMcpConfig
68
- } from "./chunk-KWNUZ4LR.js";
68
+ } from "./chunk-MBP3XG57.js";
69
69
  import {
70
70
  CLOUD_COORDINATOR_BUSY_REPLY,
71
71
  CLOUD_COORDINATOR_STOPPED_REPLY,
@@ -79,6 +79,7 @@ import {
79
79
  createGlobalChat,
80
80
  ensureCloudCoordinator,
81
81
  ensureSlackCoordinator,
82
+ findSlackCoordinator,
82
83
  healOrchestrationSoccerTitles,
83
84
  isCloudCoordinatorThread,
84
85
  isGlobalRepoPath,
@@ -92,7 +93,7 @@ import {
92
93
  parseForceStopMessage,
93
94
  slackCoordinatorSourceRef,
94
95
  takenTeamSlugsForOrchestration
95
- } from "./chunk-CLGO7TLO.js";
96
+ } from "./chunk-FO67IJTY.js";
96
97
  import {
97
98
  COORDINATOR_TOOL_PLAYBOOK,
98
99
  SLACK_REPLY_FORMATTING,
@@ -1338,7 +1339,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
1338
1339
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
1339
1340
  );
1340
1341
  }
1341
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-M3OMVDDH.js");
1342
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-RSQXRLT7.js");
1342
1343
  if (isGlobalThread2(thread)) {
1343
1344
  const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-AKEY4WSO.js");
1344
1345
  ensureGlobalCoordinatorCwd2(
@@ -3833,7 +3834,7 @@ async function createThread(input, _onSetupLine) {
3833
3834
  return readThread(thread.id) ?? thread;
3834
3835
  }
3835
3836
  async function listLinearIssues(agent, repoPath) {
3836
- const { getAdapter: getAdapter2 } = await import("./agents-WS5QV6LE.js");
3837
+ const { getAdapter: getAdapter2 } = await import("./agents-3MWWWSMF.js");
3837
3838
  await requireAgent(agent, { requireLinear: true });
3838
3839
  const adapter = getAdapter2(agent);
3839
3840
  if (!adapter.listLinearIssues) {
@@ -3913,6 +3914,7 @@ function createChatTab(input) {
3913
3914
  if (isOrchestratorThread(from) || binding.sourceType === "orchestration") {
3914
3915
  assertOrchestratorCapableAgent(nextAgent);
3915
3916
  }
3917
+ const singletonInbox = isSlackCoordinatorThread(from) || isCloudCoordinatorThread(from);
3916
3918
  const thread = createEmptyThread({
3917
3919
  title,
3918
3920
  // Chat-tab nicknames (soccer team or explicit) must stick. Post-turn
@@ -3920,6 +3922,10 @@ function createChatTab(input) {
3920
3922
  // shared worktree folder name (e.g. fork "Arsenal" → "Monaco").
3921
3923
  userSetTitle: true,
3922
3924
  ...binding,
3925
+ // Slack / Brightsy cloud identity stays on the original chat. A + tab
3926
+ // that copies `slack:team:user` would steal inbound DMs after you close
3927
+ // the connected chat.
3928
+ sourceRef: singletonInbox ? title : binding.sourceRef,
3923
3929
  agent: nextAgent,
3924
3930
  model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
3925
3931
  effort: input.effort !== void 0 ? input.effort : from.effort,
@@ -4381,7 +4387,7 @@ async function adoptThread(input) {
4381
4387
  messages: input.messages ?? []
4382
4388
  });
4383
4389
  writeThread(thread);
4384
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ERZC7ULY.js");
4390
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-4ZY4QPWQ.js");
4385
4391
  await ensureWorkspace2(repoPath);
4386
4392
  return thread;
4387
4393
  }
@@ -6126,6 +6132,9 @@ var Orchestrator = class {
6126
6132
  }
6127
6133
  return withThreadLock(thread.id, async () => {
6128
6134
  const current = this.requireThread(thread.id);
6135
+ if (current.status === "archived") {
6136
+ throw new Error(`Thread is archived: ${thread.id}`);
6137
+ }
6129
6138
  const queue = [...current.queue, prompt];
6130
6139
  this.haltDrain.delete(thread.id);
6131
6140
  const patch = { queue, status: "queued" };
@@ -7376,7 +7385,7 @@ var Orchestrator = class {
7376
7385
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
7377
7386
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
7378
7387
  try {
7379
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ERZC7ULY.js");
7388
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-4ZY4QPWQ.js");
7380
7389
  await ensureWorkspace2(thread.repoPath);
7381
7390
  } catch {
7382
7391
  }
@@ -10480,11 +10489,16 @@ function slackInboundSuperseded(opts) {
10480
10489
  }
10481
10490
  return opts.currentInboundGeneration() !== opts.inboundGeneration;
10482
10491
  }
10483
- function interruptSlackCoordinatorForInbound(msg, agent, log = () => void 0) {
10492
+ function slackCoordinatorGone(err) {
10493
+ const errMsg = err instanceof Error ? err.message : String(err);
10494
+ return /thread not found|thread is archived/i.test(errMsg);
10495
+ }
10496
+ function interruptSlackCoordinatorForInbound(msg, _agent, log = () => void 0) {
10484
10497
  const userId = msg.userId?.trim();
10485
10498
  if (!userId) return false;
10486
10499
  try {
10487
- const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
10500
+ const coordinator = findSlackCoordinator(msg.teamId, userId);
10501
+ if (!coordinator) return false;
10488
10502
  const fresh = readThread(coordinator.id) ?? coordinator;
10489
10503
  if (fresh.status !== "running" && fresh.status !== "queued") return false;
10490
10504
  getOrchestrator().stop(fresh.id, { clearQueue: true });
@@ -10650,15 +10664,16 @@ async function handleSlackInbound(msg, opts) {
10650
10664
  log(`skip superseded ${msg.kind} ${msg.ts}`);
10651
10665
  return;
10652
10666
  }
10653
- const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
10654
- let fresh = readThread(coordinator.id) ?? coordinator;
10655
10667
  if (isSlackStopCommand(msg.text)) {
10656
- try {
10657
- getOrchestrator().stop(fresh.id, { clearQueue: true });
10658
- log(`stop ${msg.kind} ${msg.ts} \u2192 coordinator ${fresh.id.slice(0, 8)}`);
10659
- } catch (err) {
10660
- const errMsg = err instanceof Error ? err.message : String(err);
10661
- log(`stop ${msg.ts}: ${errMsg}`);
10668
+ const live = findSlackCoordinator(msg.teamId, userId);
10669
+ if (live) {
10670
+ try {
10671
+ getOrchestrator().stop(live.id, { clearQueue: true });
10672
+ log(`stop ${msg.kind} ${msg.ts} \u2192 coordinator ${live.id.slice(0, 8)}`);
10673
+ } catch (err) {
10674
+ const errMsg = err instanceof Error ? err.message : String(err);
10675
+ log(`stop ${msg.ts}: ${errMsg}`);
10676
+ }
10662
10677
  }
10663
10678
  if (slackInboundSuperseded(opts)) {
10664
10679
  log(`skip superseded stop reply ${msg.ts}`);
@@ -10668,34 +10683,65 @@ async function handleSlackInbound(msg, opts) {
10668
10683
  log(`replied stopped ${msg.ts}`);
10669
10684
  return;
10670
10685
  }
10686
+ const opened = ensureSlackCoordinator(msg.teamId, userId, agent);
10687
+ let fresh = readThread(opened.id) ?? opened;
10671
10688
  if (fresh.status === "running" || fresh.status === "queued") {
10672
10689
  interruptSlackCoordinatorForInbound(msg, agent, log);
10673
- fresh = readThread(coordinator.id) ?? coordinator;
10690
+ fresh = readThread(fresh.id) ?? fresh;
10674
10691
  }
10675
10692
  log(
10676
10693
  `run ${msg.kind} ${msg.ts} user ${userId} \u2192 coordinator ${fresh.id.slice(0, 8)} (${inventory.length} workspace${inventory.length === 1 ? "" : "s"})`
10677
10694
  );
10678
10695
  const prompt = formatSlackInboundPrompt(msg);
10679
- setSlackReplyTarget({
10680
- threadId: fresh.id,
10681
- teamId: msg.teamId,
10682
- channelId: msg.channelId,
10683
- threadTs: slackReplyThreadTs(msg)
10684
- });
10685
10696
  const orch = getOrchestrator();
10697
+ const bindReplyTarget = (threadId) => {
10698
+ setSlackReplyTarget({
10699
+ threadId,
10700
+ teamId: msg.teamId,
10701
+ channelId: msg.channelId,
10702
+ threadTs: slackReplyThreadTs(msg)
10703
+ });
10704
+ };
10705
+ bindReplyTarget(fresh.id);
10706
+ const runTurn = async (threadId) => {
10707
+ await orch.send(threadId, prompt);
10708
+ await orch.waitForTurn(threadId, 14 * 60 * 1e3);
10709
+ };
10686
10710
  let reply;
10687
10711
  try {
10688
- await orch.send(fresh.id, prompt);
10689
- await orch.waitForTurn(fresh.id, 14 * 60 * 1e3);
10712
+ try {
10713
+ await runTurn(fresh.id);
10714
+ } catch (err) {
10715
+ if (!slackCoordinatorGone(err)) throw err;
10716
+ log(`coordinator ${fresh.id.slice(0, 8)} gone, opening a new chat`);
10717
+ fresh = ensureSlackCoordinator(msg.teamId, userId, agent, { forceNew: true });
10718
+ bindReplyTarget(fresh.id);
10719
+ await runTurn(fresh.id);
10720
+ }
10690
10721
  if (slackInboundSuperseded(opts)) {
10691
10722
  log(`turn finished ${msg.ts} (superseded)`);
10692
10723
  return;
10693
10724
  }
10694
- const after = readThread(fresh.id);
10695
- if (!after || after.status === "stopped" || after.status === "archived") {
10725
+ let after = readThread(fresh.id);
10726
+ if (after?.status === "stopped") {
10696
10727
  log(`turn finished ${msg.ts} (interrupted, skip post)`);
10697
10728
  return;
10698
10729
  }
10730
+ if (!after || after.status === "archived") {
10731
+ log(`coordinator ${fresh.id.slice(0, 8)} closed, opening a new chat`);
10732
+ fresh = ensureSlackCoordinator(msg.teamId, userId, agent, { forceNew: true });
10733
+ bindReplyTarget(fresh.id);
10734
+ await runTurn(fresh.id);
10735
+ if (slackInboundSuperseded(opts)) {
10736
+ log(`turn finished ${msg.ts} (superseded)`);
10737
+ return;
10738
+ }
10739
+ after = readThread(fresh.id);
10740
+ if (!after || after.status === "stopped" || after.status === "archived") {
10741
+ log(`turn finished ${msg.ts} (interrupted, skip post)`);
10742
+ return;
10743
+ }
10744
+ }
10699
10745
  reply = orch.getTurnResult(fresh.id).text.trim();
10700
10746
  } catch (err) {
10701
10747
  if (slackInboundSuperseded(opts)) {
@@ -10703,8 +10749,7 @@ async function handleSlackInbound(msg, opts) {
10703
10749
  return;
10704
10750
  }
10705
10751
  const errMsg = err instanceof Error ? err.message : String(err);
10706
- const gone = /thread not found/i.test(errMsg);
10707
- if (gone) {
10752
+ if (slackCoordinatorGone(err)) {
10708
10753
  log(`turn finished ${msg.ts} (thread gone, skip post)`);
10709
10754
  return;
10710
10755
  }
@@ -11518,6 +11563,7 @@ export {
11518
11563
  findConventionSetup,
11519
11564
  findInvalidCacheControlTtlOrder,
11520
11565
  findOrphanWorktrees,
11566
+ findSlackCoordinator,
11521
11567
  findThreadByRef,
11522
11568
  findThreadForStackLayer,
11523
11569
  flattenTurnInput,
@@ -5167,6 +5167,7 @@ __export(global_workspace_exports, {
5167
5167
  createGlobalChat: () => createGlobalChat,
5168
5168
  ensureCloudCoordinator: () => ensureCloudCoordinator,
5169
5169
  ensureSlackCoordinator: () => ensureSlackCoordinator,
5170
+ findSlackCoordinator: () => findSlackCoordinator,
5170
5171
  globalAgentCwd: () => globalAgentCwd,
5171
5172
  healOrchestrationSoccerTitles: () => healOrchestrationSoccerTitles,
5172
5173
  isCloudCoordinatorThread: () => isCloudCoordinatorThread,
@@ -5313,42 +5314,40 @@ function findSlackCoordinator(teamId, userId) {
5313
5314
  (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
5314
5315
  );
5315
5316
  }
5316
- function ensureSlackCoordinator(teamId, userId, agent) {
5317
+ function ensureSlackCoordinator(teamId, userId, agent, opts) {
5317
5318
  const defaults = resolveThreadDefaults();
5318
5319
  const desired = assertOrchestratorCapableAgent(agent);
5319
5320
  const ref = slackCoordinatorSourceRef(teamId, userId);
5320
- const existing = findSlackCoordinator(teamId, userId);
5321
- if (existing) {
5322
- const patch = {};
5323
- if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
5324
- patch.repoPath = GLOBAL_WORKSPACE_ID;
5325
- patch.worktreePath = globalAgentCwd();
5326
- patch.branchName = "global";
5327
- }
5328
- const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
5329
- const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
5330
- if (canRetarget) {
5331
- if (existing.agent !== desired) patch.agent = desired;
5332
- if (existing.model !== defaults.model) patch.model = defaults.model;
5333
- if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
5334
- if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
5335
- }
5336
- if (Object.keys(patch).length > 0) {
5337
- return updateThread(existing.id, patch);
5321
+ if (!opts?.forceNew) {
5322
+ const existing = findSlackCoordinator(teamId, userId);
5323
+ if (existing) {
5324
+ const patch = {};
5325
+ if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
5326
+ patch.repoPath = GLOBAL_WORKSPACE_ID;
5327
+ patch.worktreePath = globalAgentCwd();
5328
+ patch.branchName = "global";
5329
+ }
5330
+ const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
5331
+ const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
5332
+ if (canRetarget) {
5333
+ if (existing.agent !== desired) patch.agent = desired;
5334
+ if (existing.model !== defaults.model) patch.model = defaults.model;
5335
+ if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
5336
+ if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
5337
+ }
5338
+ if (Object.keys(patch).length > 0) {
5339
+ return updateThread(existing.id, patch);
5340
+ }
5341
+ return existing;
5338
5342
  }
5339
- return existing;
5340
5343
  }
5341
- const created = createGlobalChat({
5344
+ return createGlobalChat({
5342
5345
  sourceRef: ref,
5343
5346
  agent: desired,
5344
5347
  model: defaults.model,
5345
5348
  effort: defaults.effort,
5346
5349
  fast: defaults.fast
5347
5350
  });
5348
- const all = listThreads({ includeArchived: true }).filter(
5349
- (t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
5350
- ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
5351
- return all[0] ?? created;
5352
5351
  }
5353
5352
  function ensureCloudCoordinator(agent) {
5354
5353
  const defaults = resolveThreadDefaults();
@@ -11014,6 +11013,7 @@ function createChatTab(input) {
11014
11013
  if (isOrchestratorThread(from) || binding.sourceType === "orchestration") {
11015
11014
  assertOrchestratorCapableAgent(nextAgent);
11016
11015
  }
11016
+ const singletonInbox = isSlackCoordinatorThread(from) || isCloudCoordinatorThread(from);
11017
11017
  const thread = createEmptyThread({
11018
11018
  title,
11019
11019
  // Chat-tab nicknames (soccer team or explicit) must stick. Post-turn
@@ -11021,6 +11021,10 @@ function createChatTab(input) {
11021
11021
  // shared worktree folder name (e.g. fork "Arsenal" → "Monaco").
11022
11022
  userSetTitle: true,
11023
11023
  ...binding,
11024
+ // Slack / Brightsy cloud identity stays on the original chat. A + tab
11025
+ // that copies `slack:team:user` would steal inbound DMs after you close
11026
+ // the connected chat.
11027
+ sourceRef: singletonInbox ? title : binding.sourceRef,
11024
11028
  agent: nextAgent,
11025
11029
  model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
11026
11030
  effort: input.effort !== void 0 ? input.effort : from.effort,
@@ -13782,6 +13786,9 @@ var Orchestrator = class {
13782
13786
  }
13783
13787
  return withThreadLock(thread.id, async () => {
13784
13788
  const current = this.requireThread(thread.id);
13789
+ if (current.status === "archived") {
13790
+ throw new Error(`Thread is archived: ${thread.id}`);
13791
+ }
13785
13792
  const queue = [...current.queue, prompt];
13786
13793
  this.haltDrain.delete(thread.id);
13787
13794
  const patch = { queue, status: "queued" };
@@ -17,14 +17,14 @@ import {
17
17
  resolveQuotaFallbackAgent,
18
18
  sideboardMcpProfile,
19
19
  summarizeTurnStderr
20
- } from "../chunk-WBX46OPD.js";
20
+ } from "../chunk-FYS2BULQ.js";
21
21
  import "../chunk-DKHGWYWR.js";
22
22
  import {
23
23
  addWorkspace,
24
24
  ensureWorkspace,
25
25
  removeWorkspace,
26
26
  syncWorkspacesFromThreads
27
- } from "../chunk-6XBXVXX2.js";
27
+ } from "../chunk-OANJQTVG.js";
28
28
  import {
29
29
  extractPresentedPlan,
30
30
  readPlanFile,
@@ -41,8 +41,9 @@ import {
41
41
  isGlobalRepoPath,
42
42
  isGlobalThread,
43
43
  isOrchestratorThread,
44
+ isSlackCoordinatorThread,
44
45
  orchestratorSessionPoisonedByBuiltins
45
- } from "../chunk-NR6APJLD.js";
46
+ } from "../chunk-HI2OTFFR.js";
46
47
  import {
47
48
  SLACK_REPLY_FORMATTING,
48
49
  coordinatorSystemPrompt,
@@ -943,7 +944,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
943
944
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
944
945
  );
945
946
  }
946
- const { isGlobalThread: isGlobalThread2 } = await import("../global-workspace-3GNPQCLE.js");
947
+ const { isGlobalThread: isGlobalThread2 } = await import("../global-workspace-WMF3BJP5.js");
947
948
  if (isGlobalThread2(thread)) {
948
949
  const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("../coordinator-prompt-OQOOD5ET.js");
949
950
  ensureGlobalCoordinatorCwd2(
@@ -1851,7 +1852,7 @@ async function createThread(input, _onSetupLine) {
1851
1852
  return readThread(thread.id) ?? thread;
1852
1853
  }
1853
1854
  async function listLinearIssues(agent, repoPath) {
1854
- const { getAdapter: getAdapter2 } = await import("../agents-HBLA6FEV.js");
1855
+ const { getAdapter: getAdapter2 } = await import("../agents-ESJKIQQA.js");
1855
1856
  await requireAgent(agent, { requireLinear: true });
1856
1857
  const adapter = getAdapter2(agent);
1857
1858
  if (!adapter.listLinearIssues) {
@@ -2205,6 +2206,7 @@ function createChatTab(input) {
2205
2206
  if (isOrchestratorThread(from) || binding.sourceType === "orchestration") {
2206
2207
  assertOrchestratorCapableAgent(nextAgent);
2207
2208
  }
2209
+ const singletonInbox = isSlackCoordinatorThread(from) || isCloudCoordinatorThread(from);
2208
2210
  const thread = createEmptyThread({
2209
2211
  title,
2210
2212
  // Chat-tab nicknames (soccer team or explicit) must stick. Post-turn
@@ -2212,6 +2214,10 @@ function createChatTab(input) {
2212
2214
  // shared worktree folder name (e.g. fork "Arsenal" → "Monaco").
2213
2215
  userSetTitle: true,
2214
2216
  ...binding,
2217
+ // Slack / Brightsy cloud identity stays on the original chat. A + tab
2218
+ // that copies `slack:team:user` would steal inbound DMs after you close
2219
+ // the connected chat.
2220
+ sourceRef: singletonInbox ? title : binding.sourceRef,
2215
2221
  agent: nextAgent,
2216
2222
  model: input.model !== void 0 ? input.model : input.agent && input.agent !== from.agent ? null : from.model,
2217
2223
  effort: input.effort !== void 0 ? input.effort : from.effort,
@@ -2724,7 +2730,7 @@ async function adoptThread(input) {
2724
2730
  messages: input.messages ?? []
2725
2731
  });
2726
2732
  writeThread(thread);
2727
- const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-J4WG6UFR.js");
2733
+ const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-MZVQHRSJ.js");
2728
2734
  await ensureWorkspace2(repoPath);
2729
2735
  return thread;
2730
2736
  }
@@ -4942,6 +4948,9 @@ var Orchestrator = class {
4942
4948
  }
4943
4949
  return withThreadLock(thread.id, async () => {
4944
4950
  const current = this.requireThread(thread.id);
4951
+ if (current.status === "archived") {
4952
+ throw new Error(`Thread is archived: ${thread.id}`);
4953
+ }
4945
4954
  const queue = [...current.queue, prompt];
4946
4955
  this.haltDrain.delete(thread.id);
4947
4956
  const patch = { queue, status: "queued" };
@@ -6192,7 +6201,7 @@ var Orchestrator = class {
6192
6201
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
6193
6202
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
6194
6203
  try {
6195
- const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-J4WG6UFR.js");
6204
+ const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-MZVQHRSJ.js");
6196
6205
  await ensureWorkspace2(thread.repoPath);
6197
6206
  } catch {
6198
6207
  }
@@ -4,8 +4,8 @@ import {
4
4
  listWorkspaces,
5
5
  removeWorkspace,
6
6
  syncWorkspacesFromThreads
7
- } from "./chunk-QKYO6BHB.js";
8
- import "./chunk-CLGO7TLO.js";
7
+ } from "./chunk-UYQYK2RY.js";
8
+ import "./chunk-FO67IJTY.js";
9
9
  import "./chunk-XUWDLRAE.js";
10
10
  import "./chunk-CIRXAYWS.js";
11
11
  import "./chunk-FKOIHGKV.js";
@@ -6,8 +6,8 @@ import {
6
6
  listWorkspaces,
7
7
  removeWorkspace,
8
8
  syncWorkspacesFromThreads
9
- } from "./chunk-6XBXVXX2.js";
10
- import "./chunk-NR6APJLD.js";
9
+ } from "./chunk-OANJQTVG.js";
10
+ import "./chunk-HI2OTFFR.js";
11
11
  import "./chunk-XH2GS2LO.js";
12
12
  import "./chunk-R7BQBSDT.js";
13
13
  import "./chunk-B3SJXYIJ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.96",
3
+ "version": "0.1.98",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",