@sideboard-ai/core 0.1.92 → 0.1.96

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1854,6 +1854,7 @@ type CursorTurnRequest = {
1854
1854
  * Must be passed on create and resume — Cursor does not persist them.
1855
1855
  */
1856
1856
  mcpServers?: Record<string, {
1857
+ type?: 'stdio';
1857
1858
  command: string;
1858
1859
  args?: string[];
1859
1860
  env?: Record<string, string>;
@@ -4241,7 +4242,6 @@ interface SlackSocketModeOptions {
4241
4242
  WebSocketImpl?: SlackWebSocketCtor;
4242
4243
  }
4243
4244
 
4244
- declare const SLACK_LISTEN_BUSY_REPLY: string;
4245
4245
  declare const SLACK_LISTEN_STOPPED_REPLY = "Sideboard stopped the in-progress turn. Send another message when you want to continue.";
4246
4246
  declare const SLACK_LISTEN_TIMEOUT_REPLY: string;
4247
4247
  interface SlackListenOptions {
@@ -4256,16 +4256,29 @@ interface SlackListenOptions {
4256
4256
  postReply?: (msg: SlackInboundMessage, text: string) => Promise<void>;
4257
4257
  /** Tests: ack reactions without talking to Slack Web API. */
4258
4258
  addReaction?: (msg: SlackInboundMessage, name: string) => Promise<void>;
4259
+ /**
4260
+ * Listen session token. After waitForTurn, skip posting if a newer inbound
4261
+ * superseded this turn (interrupt-and-replace).
4262
+ */
4263
+ inboundGeneration?: number;
4264
+ currentInboundGeneration?: () => number;
4265
+ /** Listen already acked; skip the eyes reaction in handleSlackInbound. */
4266
+ skipAck?: boolean;
4259
4267
  }
4268
+ /**
4269
+ * Kill an in-flight Slack coordinator turn so a follow-up can start immediately.
4270
+ * Same force-stop as MCP `send_to_thread` (`clearQueue: true`).
4271
+ */
4272
+ declare function interruptSlackCoordinatorForInbound(msg: SlackInboundMessage, agent: AgentKind, log?: (line: string) => void): boolean;
4260
4273
  declare function formatSlackInboundPrompt(msg: SlackInboundMessage): string;
4261
4274
  /**
4262
4275
  * Prefix Slack replies with This Mac's destination (`Work: …`) so a user with
4263
4276
  * more than one device can see who answered and address follow-ups the same way.
4264
4277
  */
4265
4278
  declare function formatSlackSignedReply(deviceLabel: string, text: string): string;
4266
- /** Slack emoji short name for “seen / got it”. */
4267
- declare const SLACK_SEEN_REACTION = "+1";
4268
- /** Thumbs-up the inbound message so Slack shows the bot saw it. */
4279
+ /** Slack emoji short name for “seen / looking at this”. */
4280
+ declare const SLACK_SEEN_REACTION = "eyes";
4281
+ /** Eyes-react the inbound message so Slack shows the bot saw it. */
4269
4282
  declare function ackSlackInboundSeen(msg: SlackInboundMessage, opts: Pick<SlackListenOptions, 'addReaction' | 'fetchImpl' | 'onLog'>): Promise<void>;
4270
4283
  declare function handleSlackInbound(msg: SlackInboundMessage, opts: SlackListenOptions): Promise<void>;
4271
4284
  /**
@@ -4450,4 +4463,4 @@ interface SlackRelayClientOptions {
4450
4463
  */
4451
4464
  declare function runSlackRelayClient(opts: SlackRelayClientOptions): Promise<void>;
4452
4465
 
4453
- 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_BUSY_REPLY, 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, 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 };
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 };
package/dist/index.js CHANGED
@@ -65,7 +65,7 @@ import {
65
65
  threadRequestsBrightsyMcp,
66
66
  totalTokens,
67
67
  writeInjectedMcpConfig
68
- } from "./chunk-35LKGGOC.js";
68
+ } from "./chunk-KWNUZ4LR.js";
69
69
  import {
70
70
  CLOUD_COORDINATOR_BUSY_REPLY,
71
71
  CLOUD_COORDINATOR_STOPPED_REPLY,
@@ -2151,23 +2151,24 @@ async function countUnpushedCommits(worktreePath) {
2151
2151
  reject: false
2152
2152
  });
2153
2153
  const branch = head.stdout.trim();
2154
+ if (branch && branch !== "HEAD") {
2155
+ const remote = await git(
2156
+ ["rev-list", "--count", `origin/${branch}..HEAD`],
2157
+ worktreePath,
2158
+ { reject: false }
2159
+ );
2160
+ if (remote.exitCode === 0) {
2161
+ const n2 = Number(remote.stdout.trim());
2162
+ return Number.isFinite(n2) ? n2 : 0;
2163
+ }
2164
+ }
2154
2165
  const upstream = await git(
2155
2166
  ["rev-list", "--count", "@{upstream}..HEAD"],
2156
2167
  worktreePath,
2157
2168
  { reject: false }
2158
2169
  );
2159
- if (upstream.exitCode === 0) {
2160
- const n2 = Number(upstream.stdout.trim());
2161
- return Number.isFinite(n2) ? n2 : 0;
2162
- }
2163
- if (!branch || branch === "HEAD") return 0;
2164
- const remote = await git(
2165
- ["rev-list", "--count", `origin/${branch}..HEAD`],
2166
- worktreePath,
2167
- { reject: false }
2168
- );
2169
- if (remote.exitCode !== 0) return 0;
2170
- const n = Number(remote.stdout.trim());
2170
+ if (upstream.exitCode !== 0) return 0;
2171
+ const n = Number(upstream.stdout.trim());
2171
2172
  return Number.isFinite(n) ? n : 0;
2172
2173
  }
2173
2174
  function splitCombinedDiff(stdout) {
@@ -3832,7 +3833,7 @@ async function createThread(input, _onSetupLine) {
3832
3833
  return readThread(thread.id) ?? thread;
3833
3834
  }
3834
3835
  async function listLinearIssues(agent, repoPath) {
3835
- const { getAdapter: getAdapter2 } = await import("./agents-TUV4NH7S.js");
3836
+ const { getAdapter: getAdapter2 } = await import("./agents-WS5QV6LE.js");
3836
3837
  await requireAgent(agent, { requireLinear: true });
3837
3838
  const adapter = getAdapter2(agent);
3838
3839
  if (!adapter.listLinearIssues) {
@@ -5810,6 +5811,11 @@ function isPidAlive(pid) {
5810
5811
  return false;
5811
5812
  }
5812
5813
  }
5814
+ function writeLiveStatus(threadId, status, lastError) {
5815
+ const latest = readThread(threadId);
5816
+ if (!latest || latest.status === "archived") return latest;
5817
+ return setStatus(threadId, status, lastError);
5818
+ }
5813
5819
  var Orchestrator = class {
5814
5820
  events = new EventEmitter();
5815
5821
  processes = /* @__PURE__ */ new Map();
@@ -6115,6 +6121,9 @@ var Orchestrator = class {
6115
6121
  }
6116
6122
  async send(threadRef, prompt) {
6117
6123
  const thread = this.requireThread(threadRef);
6124
+ if (thread.status === "archived") {
6125
+ throw new Error(`Thread is archived: ${thread.id}`);
6126
+ }
6118
6127
  return withThreadLock(thread.id, async () => {
6119
6128
  const current = this.requireThread(thread.id);
6120
6129
  const queue = [...current.queue, prompt];
@@ -6208,7 +6217,7 @@ var Orchestrator = class {
6208
6217
  break;
6209
6218
  }
6210
6219
  const thread = readThread(threadId);
6211
- if (!thread || thread.queue.length === 0) {
6220
+ if (!thread || thread.status === "archived" || thread.queue.length === 0) {
6212
6221
  if (thread && thread.status === "queued") {
6213
6222
  setStatus(threadId, "idle");
6214
6223
  this.emit({ type: "status_changed", threadId, status: "idle" });
@@ -6239,14 +6248,17 @@ var Orchestrator = class {
6239
6248
  }
6240
6249
  }
6241
6250
  async runTurn(threadId, prompt) {
6242
- let thread = this.requireThread(threadId);
6251
+ const existing = readThread(threadId);
6252
+ if (!existing || existing.status === "archived") return;
6253
+ let thread = existing;
6243
6254
  if (isGlobalThread(thread) && thread.sessionId && orchestratorSessionPoisonedByBuiltins(thread)) {
6244
6255
  thread = updateThread(threadId, { sessionId: null });
6245
6256
  }
6257
+ const running = writeLiveStatus(threadId, "running");
6258
+ if (!running || running.status !== "running") return;
6246
6259
  this.runningCount += 1;
6247
6260
  const turnStartedAt = Date.now();
6248
6261
  this.startingTurns.add(threadId);
6249
- setStatus(threadId, "running");
6250
6262
  this.emit({ type: "status_changed", threadId, status: "running" });
6251
6263
  this.emit({ type: "turn_started", threadId, prompt });
6252
6264
  try {
@@ -6517,8 +6529,8 @@ var Orchestrator = class {
6517
6529
  ts: (/* @__PURE__ */ new Date()).toISOString()
6518
6530
  });
6519
6531
  }
6520
- const afterTurn = this.requireThread(threadId);
6521
- if (afterTurn.planMode && afterTurn.worktreePath?.trim()) {
6532
+ const afterTurn = readThread(threadId);
6533
+ if (afterTurn && afterTurn.status !== "archived" && afterTurn.planMode && afterTurn.worktreePath?.trim()) {
6522
6534
  const presented = extractPresentedPlan(parts);
6523
6535
  const exited = parts.some(
6524
6536
  (p) => p.type === "tool" && /exitplanmode/i.test(p.name)
@@ -6531,29 +6543,34 @@ var Orchestrator = class {
6531
6543
  }
6532
6544
  }
6533
6545
  }
6534
- if (afterTurn.planMode && afterTurn.agent === "claude" && parts.some(
6546
+ if (afterTurn && afterTurn.status !== "archived" && afterTurn.planMode && afterTurn.agent === "claude" && parts.some(
6535
6547
  (p) => p.type === "tool" && /exitplanmode/i.test(p.name)
6536
6548
  )) {
6537
6549
  updateThread(threadId, { sessionId: null });
6538
6550
  }
6539
6551
  await syncThreadBranchFromGit(threadId);
6540
6552
  if (this.stoppedTurns.has(threadId)) {
6541
- setStatus(threadId, "stopped");
6542
- this.emit({ type: "status_changed", threadId, status: "stopped" });
6553
+ const stopped = writeLiveStatus(threadId, "stopped");
6554
+ if (stopped?.status === "stopped") {
6555
+ this.emit({ type: "status_changed", threadId, status: "stopped" });
6556
+ }
6543
6557
  this.emit({ type: "turn_finished", threadId, exitCode });
6544
6558
  } else {
6545
6559
  const failDetail = formatTurnExitError(exitCode, detail);
6546
6560
  const explainedInChat = exitCode !== 0 && Boolean(chatText) && (looksLikeAgentFailureMessage(chatText) || failDetail && chatText.includes(failDetail.replace(/^exit\s*\d+:\s*/i, "").trim()));
6547
- setStatus(
6561
+ const nextStatus = exitCode === 0 ? "idle" : "error";
6562
+ const written = writeLiveStatus(
6548
6563
  threadId,
6549
- exitCode === 0 ? "idle" : "error",
6564
+ nextStatus,
6550
6565
  exitCode === 0 || explainedInChat ? null : failDetail
6551
6566
  );
6552
- this.emit({
6553
- type: "status_changed",
6554
- threadId,
6555
- status: exitCode === 0 ? "idle" : "error"
6556
- });
6567
+ if (written && written.status !== "archived") {
6568
+ this.emit({
6569
+ type: "status_changed",
6570
+ threadId,
6571
+ status: written.status
6572
+ });
6573
+ }
6557
6574
  this.emit({ type: "turn_finished", threadId, exitCode });
6558
6575
  if (exitCode !== 0) {
6559
6576
  const blob = [chatText, detail].filter(Boolean).join("\n");
@@ -6564,13 +6581,17 @@ var Orchestrator = class {
6564
6581
  const message = err instanceof Error ? err.message : String(err);
6565
6582
  await syncThreadBranchFromGit(threadId).catch(() => void 0);
6566
6583
  if (this.stoppedTurns.has(threadId)) {
6567
- setStatus(threadId, "stopped");
6568
- this.emit({ type: "status_changed", threadId, status: "stopped" });
6584
+ const stopped = writeLiveStatus(threadId, "stopped");
6585
+ if (stopped?.status === "stopped") {
6586
+ this.emit({ type: "status_changed", threadId, status: "stopped" });
6587
+ }
6569
6588
  this.emit({ type: "turn_finished", threadId, exitCode: 1 });
6570
6589
  } else {
6571
- setStatus(threadId, "error", message);
6572
- this.emit({ type: "error", threadId, message });
6573
- this.emit({ type: "status_changed", threadId, status: "error" });
6590
+ const written = writeLiveStatus(threadId, "error", message);
6591
+ if (written?.status === "error") {
6592
+ this.emit({ type: "error", threadId, message });
6593
+ this.emit({ type: "status_changed", threadId, status: "error" });
6594
+ }
6574
6595
  this.emit({ type: "turn_finished", threadId, exitCode: 1 });
6575
6596
  void this.maybeHandleOrchestrationQuotaFailover(threadId, message);
6576
6597
  }
@@ -6617,9 +6638,11 @@ var Orchestrator = class {
6617
6638
  if (handle) handle.kill();
6618
6639
  const proc = this.processes.get(`${thread.id}:agent`);
6619
6640
  if (proc) proc.kill();
6620
- setStatus(thread.id, "stopped");
6621
- this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
6622
- return this.requireThread(thread.id);
6641
+ const stopped = writeLiveStatus(thread.id, "stopped") ?? readThread(thread.id) ?? thread;
6642
+ if (stopped.status === "stopped") {
6643
+ this.emit({ type: "status_changed", threadId: thread.id, status: "stopped" });
6644
+ }
6645
+ return stopped;
6623
6646
  }
6624
6647
  async startDev(threadRef, scriptName) {
6625
6648
  const thread = this.requireThread(threadRef);
@@ -6855,11 +6878,21 @@ var Orchestrator = class {
6855
6878
  const off = this.on((event) => {
6856
6879
  if (event.type === "turn_finished" && event.threadId === thread.id) {
6857
6880
  off();
6858
- resolve(this.requireThread(thread.id));
6881
+ const latest = readThread(thread.id);
6882
+ if (!latest) {
6883
+ reject(new Error(`Thread not found: ${thread.id}`));
6884
+ return;
6885
+ }
6886
+ resolve(latest);
6859
6887
  }
6860
6888
  if (event.type === "error" && event.threadId === thread.id) {
6861
6889
  off();
6862
- resolve(this.requireThread(thread.id));
6890
+ const latest = readThread(thread.id);
6891
+ if (!latest) {
6892
+ reject(new Error(`Thread not found: ${thread.id}`));
6893
+ return;
6894
+ }
6895
+ resolve(latest);
6863
6896
  }
6864
6897
  });
6865
6898
  const timer = setInterval(() => {
@@ -6869,7 +6902,13 @@ var Orchestrator = class {
6869
6902
  reject(new Error("wait_for_turn timed out"));
6870
6903
  }
6871
6904
  const current = readThread(thread.id);
6872
- if (current && !["running", "queued"].includes(current.status)) {
6905
+ if (!current) {
6906
+ clearInterval(timer);
6907
+ off();
6908
+ reject(new Error(`Thread not found: ${thread.id}`));
6909
+ return;
6910
+ }
6911
+ if (!["running", "queued"].includes(current.status)) {
6873
6912
  clearInterval(timer);
6874
6913
  off();
6875
6914
  resolve(current);
@@ -9609,6 +9648,7 @@ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
9609
9648
  const servers = asObject(root.mcpServers);
9610
9649
  const env = stripElectronSpawnEnv(sideboard.env);
9611
9650
  servers.sideboard = {
9651
+ type: "stdio",
9612
9652
  command: sideboard.command,
9613
9653
  ...sideboard.args && sideboard.args.length > 0 ? { args: sideboard.args } : {},
9614
9654
  ...env ? { env } : {}
@@ -10417,15 +10457,10 @@ function connectSession2(ws, opts, log) {
10417
10457
  }
10418
10458
 
10419
10459
  // src/slack/listen.ts
10420
- var SLACK_LISTEN_BUSY_REPLY = [
10421
- "Sideboard is busy with an in-progress turn.",
10422
- "I did not start a new request.",
10423
- 'Send "stop" to interrupt, or try again when idle.'
10424
- ].join(" ");
10425
10460
  var SLACK_LISTEN_STOPPED_REPLY = "Sideboard stopped the in-progress turn. Send another message when you want to continue.";
10426
10461
  var SLACK_LISTEN_TIMEOUT_REPLY = [
10427
10462
  "Sideboard timed out waiting for the local agent turn to finish.",
10428
- 'Send "stop" to interrupt, or try again.'
10463
+ 'Send another message to interrupt and retry, or send "stop".'
10429
10464
  ].join(" ");
10430
10465
  var handleChain = Promise.resolve();
10431
10466
  function enqueueHandle(fn) {
@@ -10439,6 +10474,30 @@ function enqueueHandle(fn) {
10439
10474
  function refreshWorkspaces2() {
10440
10475
  return getOrchestrator().listWorkspaces();
10441
10476
  }
10477
+ function slackInboundSuperseded(opts) {
10478
+ if (opts.inboundGeneration === void 0 || !opts.currentInboundGeneration) {
10479
+ return false;
10480
+ }
10481
+ return opts.currentInboundGeneration() !== opts.inboundGeneration;
10482
+ }
10483
+ function interruptSlackCoordinatorForInbound(msg, agent, log = () => void 0) {
10484
+ const userId = msg.userId?.trim();
10485
+ if (!userId) return false;
10486
+ try {
10487
+ const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
10488
+ const fresh = readThread(coordinator.id) ?? coordinator;
10489
+ if (fresh.status !== "running" && fresh.status !== "queued") return false;
10490
+ getOrchestrator().stop(fresh.id, { clearQueue: true });
10491
+ log(
10492
+ `interrupt ${msg.kind} ${msg.ts} \u2192 coordinator ${fresh.id.slice(0, 8)} (${fresh.status})`
10493
+ );
10494
+ return true;
10495
+ } catch (err) {
10496
+ const errMsg = err instanceof Error ? err.message : String(err);
10497
+ log(`interrupt ${msg.ts}: ${errMsg}`);
10498
+ return false;
10499
+ }
10500
+ }
10442
10501
  function formatSlackInboundPrompt(msg) {
10443
10502
  const kind = msg.kind === "mention" ? "Slack @mention" : "Slack DM";
10444
10503
  return `${kind}
@@ -10467,7 +10526,7 @@ function slackReplyThreadTs(msg) {
10467
10526
  if (msg.kind === "mention") return msg.ts;
10468
10527
  return void 0;
10469
10528
  }
10470
- var SLACK_SEEN_REACTION = "+1";
10529
+ var SLACK_SEEN_REACTION = "eyes";
10471
10530
  function writeTokenForTeam(teamId) {
10472
10531
  const workspaces = listSlackWorkspacesRaw();
10473
10532
  const ws = workspaces.find((w) => w.team_id === teamId);
@@ -10569,7 +10628,13 @@ async function relayCoordinatorReplyToSlack(threadId, opts) {
10569
10628
  }
10570
10629
  async function handleSlackInbound(msg, opts) {
10571
10630
  const log = opts.onLog ?? (() => void 0);
10572
- await ackSlackInboundSeen(msg, opts);
10631
+ if (!opts.skipAck) {
10632
+ await ackSlackInboundSeen(msg, opts);
10633
+ }
10634
+ if (slackInboundSuperseded(opts)) {
10635
+ log(`skip superseded ${msg.kind} ${msg.ts}`);
10636
+ return;
10637
+ }
10573
10638
  const agent = coerceOrchestratorAgent(opts.agent ?? getDefaultAgent());
10574
10639
  const workspaces = refreshWorkspaces2();
10575
10640
  for (const ws of workspaces) {
@@ -10581,25 +10646,31 @@ async function handleSlackInbound(msg, opts) {
10581
10646
  log(`skip ${msg.kind} ${msg.ts}: missing Slack user id`);
10582
10647
  return;
10583
10648
  }
10649
+ if (slackInboundSuperseded(opts)) {
10650
+ log(`skip superseded ${msg.kind} ${msg.ts}`);
10651
+ return;
10652
+ }
10584
10653
  const coordinator = ensureSlackCoordinator(msg.teamId, userId, agent);
10585
- const fresh = readThread(coordinator.id) ?? coordinator;
10654
+ let fresh = readThread(coordinator.id) ?? coordinator;
10586
10655
  if (isSlackStopCommand(msg.text)) {
10587
10656
  try {
10588
- getOrchestrator().stop(fresh.id);
10657
+ getOrchestrator().stop(fresh.id, { clearQueue: true });
10589
10658
  log(`stop ${msg.kind} ${msg.ts} \u2192 coordinator ${fresh.id.slice(0, 8)}`);
10590
10659
  } catch (err) {
10591
10660
  const errMsg = err instanceof Error ? err.message : String(err);
10592
10661
  log(`stop ${msg.ts}: ${errMsg}`);
10593
10662
  }
10663
+ if (slackInboundSuperseded(opts)) {
10664
+ log(`skip superseded stop reply ${msg.ts}`);
10665
+ return;
10666
+ }
10594
10667
  await postSlackReply(msg, SLACK_LISTEN_STOPPED_REPLY, opts);
10595
10668
  log(`replied stopped ${msg.ts}`);
10596
10669
  return;
10597
10670
  }
10598
10671
  if (fresh.status === "running" || fresh.status === "queued") {
10599
- log(`busy ${msg.kind} ${msg.ts} \u2192 coordinator ${fresh.id.slice(0, 8)} (${fresh.status})`);
10600
- await postSlackReply(msg, SLACK_LISTEN_BUSY_REPLY, opts);
10601
- log(`replied busy ${msg.ts}`);
10602
- return;
10672
+ interruptSlackCoordinatorForInbound(msg, agent, log);
10673
+ fresh = readThread(coordinator.id) ?? coordinator;
10603
10674
  }
10604
10675
  log(
10605
10676
  `run ${msg.kind} ${msg.ts} user ${userId} \u2192 coordinator ${fresh.id.slice(0, 8)} (${inventory.length} workspace${inventory.length === 1 ? "" : "s"})`
@@ -10616,9 +10687,27 @@ async function handleSlackInbound(msg, opts) {
10616
10687
  try {
10617
10688
  await orch.send(fresh.id, prompt);
10618
10689
  await orch.waitForTurn(fresh.id, 14 * 60 * 1e3);
10690
+ if (slackInboundSuperseded(opts)) {
10691
+ log(`turn finished ${msg.ts} (superseded)`);
10692
+ return;
10693
+ }
10694
+ const after = readThread(fresh.id);
10695
+ if (!after || after.status === "stopped" || after.status === "archived") {
10696
+ log(`turn finished ${msg.ts} (interrupted, skip post)`);
10697
+ return;
10698
+ }
10619
10699
  reply = orch.getTurnResult(fresh.id).text.trim();
10620
10700
  } catch (err) {
10701
+ if (slackInboundSuperseded(opts)) {
10702
+ log(`turn error ${msg.ts} (superseded)`);
10703
+ return;
10704
+ }
10621
10705
  const errMsg = err instanceof Error ? err.message : String(err);
10706
+ const gone = /thread not found/i.test(errMsg);
10707
+ if (gone) {
10708
+ log(`turn finished ${msg.ts} (thread gone, skip post)`);
10709
+ return;
10710
+ }
10622
10711
  const timedOut = /timed out|timeout/i.test(errMsg);
10623
10712
  const errorReply = timedOut ? SLACK_LISTEN_TIMEOUT_REPLY : `Sideboard coordinator error: ${errMsg}`;
10624
10713
  await postSlackReply(msg, errorReply, opts).catch((postErr) => {
@@ -10665,19 +10754,35 @@ async function runSlackListen(opts = {}) {
10665
10754
  const log = opts.onLog ?? console.log;
10666
10755
  const connected = listSlackWorkspacesRaw();
10667
10756
  const orch = getOrchestrator();
10757
+ const agent = coerceOrchestratorAgent(opts.agent ?? getDefaultAgent());
10758
+ let inboundGeneration = 0;
10668
10759
  const off = orch.on((event) => {
10669
10760
  if (event.type !== "turn_finished") return;
10670
10761
  void relayCoordinatorReplyToSlack(event.threadId, opts);
10671
10762
  });
10672
- const onInbound = (msg) => enqueueHandle(async () => {
10763
+ const onInbound = (msg) => {
10673
10764
  if (!isInboundForThisDesktop(msg)) {
10674
10765
  log(
10675
10766
  `skip ${msg.kind} ${msg.ts}: Slack user ${msg.userId ?? "?"} is not connected on this Mac`
10676
10767
  );
10677
10768
  return;
10678
10769
  }
10679
- await handleSlackInbound(msg, opts);
10680
- });
10770
+ const generation = ++inboundGeneration;
10771
+ void ackSlackInboundSeen(msg, opts);
10772
+ interruptSlackCoordinatorForInbound(msg, agent, log);
10773
+ return enqueueHandle(async () => {
10774
+ if (generation !== inboundGeneration) {
10775
+ log(`skip superseded ${msg.kind} ${msg.ts}`);
10776
+ return;
10777
+ }
10778
+ await handleSlackInbound(msg, {
10779
+ ...opts,
10780
+ skipAck: true,
10781
+ inboundGeneration: generation,
10782
+ currentInboundGeneration: () => inboundGeneration
10783
+ });
10784
+ });
10785
+ };
10681
10786
  try {
10682
10787
  const relay = (opts.relayUrl ?? slackRelayUrl()).trim();
10683
10788
  if (!relay) {
@@ -11279,7 +11384,6 @@ export {
11279
11384
  SIDEBOARD_FORCE_STOP,
11280
11385
  SIDEBOARD_MCP_ALLOWED_TOOLS,
11281
11386
  SIDEBOARD_MCP_PROFILE_ENV,
11282
- SLACK_LISTEN_BUSY_REPLY,
11283
11387
  SLACK_LISTEN_STOPPED_REPLY,
11284
11388
  SLACK_LISTEN_TIMEOUT_REPLY,
11285
11389
  SLACK_OAUTH_CANCELLED,
@@ -11497,6 +11601,7 @@ export {
11497
11601
  initializeGitRepository,
11498
11602
  inspectGitWorktree,
11499
11603
  installAgent,
11604
+ interruptSlackCoordinatorForInbound,
11500
11605
  isAskUserToolName,
11501
11606
  isBrightsyConnected,
11502
11607
  isBrightsyNdjsonLine,