scream-code 0.19.7 → 0.19.8

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/README.md CHANGED
@@ -18,9 +18,30 @@
18
18
  <a href="README.zh.md">简体中文</a>
19
19
  </p>
20
20
 
21
- <p align="center">
22
- <img width="2880" height="2880" alt="scream" src="https://github.com/user-attachments/assets/7268e848-b1b8-4540-9627-d21c94332229" />
23
- </p>
21
+ ### ❤️Sponsor
22
+
23
+ <details open>
24
+ <summary>Click to collapse</summary>
25
+
26
+ <table>
27
+ <tr>
28
+ <td width="210" align="center" valign="middle"><a href="https://todapi.work"><img src="assets/sponsor-todapi.png" alt="todapi" width="190"></a></td>
29
+ <td>
30
+
31
+ <p><strong>todapi</strong> — a high-value API gateway.</p>
32
+ <p>DeepSeek and other mainstream models from <strong>as low as 10% of list price</strong>, reached through one unified gateway: pay-as-you-go, one API key for multiple models. Powered by tier-one vendor resources with stable routes and strong value.</p>
33
+ <ul>
34
+ <li><strong>Price</strong>: DeepSeek and more from 10% of list price</li>
35
+ <li><strong>Access</strong>: one gateway, one key — switching models no longer means switching providers</li>
36
+ <li><strong>Get started</strong>: sign up at <a href="https://todapi.work">todapi.work</a></li>
37
+ </ul>
38
+ <p>Thanks to <a href="https://todapi.work">todapi</a> for sponsoring this project ❤️</p>
39
+
40
+ </td>
41
+ </tr>
42
+ </table>
43
+
44
+ </details>
24
45
 
25
46
  ---
26
47
 
@@ -5,7 +5,7 @@ const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
6
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
7
7
  import { A as sharedMemoStore } from "./src-Cu3sUIJK.mjs";
8
- import { $n as validateFeishuCredentials, A as langFromPath, An as hasEmbeddingModelCache, At as createThemeStyles, B as getSharedSpeedTracker, Bn as isSendThrottled, Bt as OSC11_RESPONSE, Cn as BUILTIN_SLASH_COMMANDS, Cr as fetchCatalogWithMeta, D as renderDiffLines, Dn as embeddingProgressLabel, Dr as saveCatalogCacheMeta, Dt as isEmptySessionHintDismissed, E as ToolCallComponent, En as setExperimentalFlags, Er as saveCatalogCache, Et as createMarkdownTheme, F as SkillActivationComponent, Fn as startLineDaemonDetached, Fr as resolveGlobalLogPath, Ft as DISABLE_TERMINAL_FOCUS_REPORTING, G as AgentGroupComponent, Gn as parseAesKey, Gt as TERMINAL_FOCUS_OUT, H as lerpGradient, Ht as OSC11_RESPONSE_PREFIX_NO_ESC, I as AssistantMessageComponent, In as stopLineDaemon, Ir as isScreamError, It as DISABLE_TERMINAL_THEME_REPORTING, J as getBreathingFrame, Jn as TuiConfigParseError, Jt as safeUsageRatio, K as WelcomeComponent, Kn as replaceTabs, Kt as TERMINAL_THEME_DARK, L as ActivityGroupComponent, Ln as UPLOAD_MEDIA_TYPE, Lr as isOrphanedToolCallError, Lt as ENABLE_TERMINAL_FOCUS_REPORTING, M as ThinkingComponent, Mn as PIXEL_PULSE_FRAMES, Mr as resolveScreamHome, Mt as getColorPalette, N as NoticeMessageComponent, Nn as PULSE_WAVE_FRAMES, Nr as flushDiagnosticLogs, Nt as detectTerminalTheme, O as renderDiffLinesClustered, On as embeddingFailureDetail, Or as ScreamHarness, Ot as isTurnElapsedEnabled, P as StatusMessageComponent, Pn as readLineDaemonStatus, Pr as log, Pt as parseOsc11BackgroundTheme, Qn as feishuFileType, R as charsForTokenBudget, Rn as WeixinApiError, Rr as SCREAM_ERROR_INFO, Rt as ENABLE_TERMINAL_THEME_REPORTING, S as readJsonlFile, Sn as buildSkillSlashCommands, Sr as DEFAULT_CATALOG_URL, T as UserMessageComponent, Tn as isExperimentalFlagEnabled, Tr as loadCatalogCacheMeta, Tt as createEditorTheme, U as lerpHex, Un as buildCdnDownloadUrl, Ut as QUERY_TERMINAL_THEME, V as GRADIENT_CYCLE_MS, Vn as validateWeixinToken, Vt as OSC11_RESPONSE_PREFIX, W as BackgroundAgentStatusComponent, Wn as decryptAesEcb, Wt as TERMINAL_FOCUS_IN, X as CompactionComponent, Xn as FeishuClient, Y as resetBreathingClock, Yn as loadTuiConfig, Yt as SubagentSlots, Z as clearGoalState, Zn as FeishuCredentialError, _n as TIP_ROTATION_INTERVAL_MS, _r as detectInstallSource, a as writeTextClipboard, an as appendStreamingArgsPreview, ar as getWeixinContextTokensFile, at as getModelCycleLevel, b as readUpdateCache, bn as getLlmNotSetMessage, br as CLI_USER_AGENT_PRODUCT, bt as supportsBalance, cn as isTodoItemShape, cr as loadLineConfig, d as isExpandable, dn as stringValue, dr as resolveTurnTimeoutMs, en as isBusy, er as LineConfigError, f as isPlanExpandable, fn as truncateErrorMessage, fr as resolveWeixinOptions, ft as handlePlanCommand, gn as SESSION_TIPS, gr as getLogDir, hn as MAIN_AGENT_ID, hr as getInputHistoryFile, i as openUrl, in as appendSessionHeaderHint, ir as getLinePidFile, it as changeThinkingLevel, j as CachedContainer, jn as startManualEmbeddingDownload, jr as isRealUserPrompt, jt as contrastTextHex, k as highlightLines, kn as getKnowledgeStore, kr as normalizeWorkDir, kt as toggleEmptySessionHint, l as disposeChildren, ln as parseStreamingArgs, lr as resolveCustomCommands, m as formatMemoryMemoForInjection, mn as EXIT_CONFIRM_WINDOW_MS, mr as getDataDir, n as clearEvalPanelState, nn as printableChar, nr as assertSinglePlatformConfig, o as syncDiagramCapabilityPrompt, on as argsRecord, or as getWeixinCursorFile, p as MoonLoader, pr as detectShellEnvironment, q as BREATHE_CYCLE_MS, qn as sanitizeShellOutput, qt as TERMINAL_THEME_LIGHT, rn as STATUS_BULLET, rr as getLineConfigPath, rt as toTerminalHyperlink, sn as formatErrorMessage, sr as getWeixinStateDir, t as dispatchInput, tn as isStreaming, tr as MINUTE_MS, u as hasDispose, un as serializeToolResultOutput, ur as resolveFeishuOptions, ut as handleFusionPlanCommand, v as selectUpdateTarget, vn as getCtrlCHint, vr as CLI_COMMAND_NAME, wn as sortSlashCommands, wr as loadCatalogCache, wt as resolveThemeSync, x as appendJsonlLine, xn as getNoActiveSessionMessage, xr as PRODUCT_NAME, xt as clearInfoPanelState, y as refreshUpdateCache, yn as getCtrlDHint, yr as CLI_UI_MODE, yt as refreshProviderBalance, z as estimateTokens, zn as WeixinClient, zt as OSC11_QUERY } from "./dispatch-BiOeRj_C.mjs";
8
+ import { $n as validateFeishuCredentials, A as langFromPath, An as hasEmbeddingModelCache, At as createThemeStyles, B as getSharedSpeedTracker, Bn as isSendThrottled, Bt as OSC11_RESPONSE, Cn as BUILTIN_SLASH_COMMANDS, Cr as fetchCatalogWithMeta, D as renderDiffLines, Dn as embeddingProgressLabel, Dr as saveCatalogCacheMeta, Dt as isEmptySessionHintDismissed, E as ToolCallComponent, En as setExperimentalFlags, Er as saveCatalogCache, Et as createMarkdownTheme, F as SkillActivationComponent, Fn as startLineDaemonDetached, Fr as resolveGlobalLogPath, Ft as DISABLE_TERMINAL_FOCUS_REPORTING, G as AgentGroupComponent, Gn as parseAesKey, Gt as TERMINAL_FOCUS_OUT, H as lerpGradient, Ht as OSC11_RESPONSE_PREFIX_NO_ESC, I as AssistantMessageComponent, In as stopLineDaemon, Ir as isScreamError, It as DISABLE_TERMINAL_THEME_REPORTING, J as getBreathingFrame, Jn as TuiConfigParseError, Jt as safeUsageRatio, K as WelcomeComponent, Kn as replaceTabs, Kt as TERMINAL_THEME_DARK, L as ActivityGroupComponent, Ln as UPLOAD_MEDIA_TYPE, Lr as isOrphanedToolCallError, Lt as ENABLE_TERMINAL_FOCUS_REPORTING, M as ThinkingComponent, Mn as PIXEL_PULSE_FRAMES, Mr as resolveScreamHome, Mt as getColorPalette, N as NoticeMessageComponent, Nn as PULSE_WAVE_FRAMES, Nr as flushDiagnosticLogs, Nt as detectTerminalTheme, O as renderDiffLinesClustered, On as embeddingFailureDetail, Or as ScreamHarness, Ot as isTurnElapsedEnabled, P as StatusMessageComponent, Pn as readLineDaemonStatus, Pr as log, Pt as parseOsc11BackgroundTheme, Qn as feishuFileType, R as charsForTokenBudget, Rn as WeixinApiError, Rr as SCREAM_ERROR_INFO, Rt as ENABLE_TERMINAL_THEME_REPORTING, S as readJsonlFile, Sn as buildSkillSlashCommands, Sr as DEFAULT_CATALOG_URL, T as UserMessageComponent, Tn as isExperimentalFlagEnabled, Tr as loadCatalogCacheMeta, Tt as createEditorTheme, U as lerpHex, Un as buildCdnDownloadUrl, Ut as QUERY_TERMINAL_THEME, V as GRADIENT_CYCLE_MS, Vn as validateWeixinToken, Vt as OSC11_RESPONSE_PREFIX, W as BackgroundAgentStatusComponent, Wn as decryptAesEcb, Wt as TERMINAL_FOCUS_IN, X as CompactionComponent, Xn as FeishuClient, Y as resetBreathingClock, Yn as loadTuiConfig, Yt as SubagentSlots, Z as clearGoalState, Zn as FeishuCredentialError, _n as TIP_ROTATION_INTERVAL_MS, _r as detectInstallSource, a as writeTextClipboard, an as appendStreamingArgsPreview, ar as getWeixinContextTokensFile, at as getModelCycleLevel, b as readUpdateCache, bn as getLlmNotSetMessage, br as CLI_USER_AGENT_PRODUCT, bt as supportsBalance, cn as isTodoItemShape, cr as loadLineConfig, d as isExpandable, dn as stringValue, dr as resolveTurnTimeoutMs, en as isBusy, er as LineConfigError, f as isPlanExpandable, fn as truncateErrorMessage, fr as resolveWeixinOptions, ft as handlePlanCommand, gn as SESSION_TIPS, gr as getLogDir, hn as MAIN_AGENT_ID, hr as getInputHistoryFile, i as openUrl, in as appendSessionHeaderHint, ir as getLinePidFile, it as changeThinkingLevel, j as CachedContainer, jn as startManualEmbeddingDownload, jr as isRealUserPrompt, jt as contrastTextHex, k as highlightLines, kn as getKnowledgeStore, kr as normalizeWorkDir, kt as toggleEmptySessionHint, l as disposeChildren, ln as parseStreamingArgs, lr as resolveCustomCommands, m as formatMemoryMemoForInjection, mn as EXIT_CONFIRM_WINDOW_MS, mr as getDataDir, n as clearEvalPanelState, nn as printableChar, nr as assertSinglePlatformConfig, o as syncDiagramCapabilityPrompt, on as argsRecord, or as getWeixinCursorFile, p as MoonLoader, pr as detectShellEnvironment, q as BREATHE_CYCLE_MS, qn as sanitizeShellOutput, qt as TERMINAL_THEME_LIGHT, rn as STATUS_BULLET, rr as getLineConfigPath, rt as toTerminalHyperlink, sn as formatErrorMessage, sr as getWeixinStateDir, t as dispatchInput, tn as isStreaming, tr as MINUTE_MS, u as hasDispose, un as serializeToolResultOutput, ur as resolveFeishuOptions, ut as handleFusionPlanCommand, v as selectUpdateTarget, vn as getCtrlCHint, vr as CLI_COMMAND_NAME, wn as sortSlashCommands, wr as loadCatalogCache, wt as resolveThemeSync, x as appendJsonlLine, xn as getNoActiveSessionMessage, xr as PRODUCT_NAME, xt as clearInfoPanelState, y as refreshUpdateCache, yn as getCtrlDHint, yr as CLI_UI_MODE, yt as refreshProviderBalance, z as estimateTokens, zn as WeixinClient, zt as OSC11_QUERY } from "./dispatch-DMntc47e.mjs";
9
9
  import { i as t, n as getLocale, r as setLocale } from "./text-input-dialog-Ce2AEFU9.mjs";
10
10
  import { createRequire } from "node:module";
11
11
  import { createHash, randomInt, randomUUID } from "node:crypto";
@@ -28,7 +28,7 @@ function optionalBuildString(value) {
28
28
  return typeof value === "string" && value.length > 0 ? value : void 0;
29
29
  }
30
30
  const SCREAM_BUILD_INFO = {
31
- version: optionalBuildString("0.19.7"),
31
+ version: optionalBuildString("0.19.8"),
32
32
  channel: optionalBuildString(""),
33
33
  commit: optionalBuildString(""),
34
34
  buildTarget: optionalBuildString("darwin-arm64")
@@ -7129,7 +7129,6 @@ var SessionEventHandler = class {
7129
7129
  providerLatencyWindow = 3;
7130
7130
  renderedSkillActivationIds = /* @__PURE__ */ new Set();
7131
7131
  renderedMcpServerStatusKeys = /* @__PURE__ */ new Map();
7132
- mcpServerStatusSpinners = /* @__PURE__ */ new Map();
7133
7132
  /**
7134
7133
  * `SendSubagentMessage` tool call → target agent id. Needed at result time
7135
7134
  * because `SubagentSlots.onMessagingEnd()` deletes its own mapping, and a
@@ -7157,7 +7156,6 @@ var SessionEventHandler = class {
7157
7156
  this.recentSubagentInstances.length = 0;
7158
7157
  this.renderedSkillActivationIds.clear();
7159
7158
  this.renderedMcpServerStatusKeys.clear();
7160
- this.stopAllMcpServerStatusSpinners();
7161
7159
  this.pendingSkillCandidates = [];
7162
7160
  this.promptedSkillCandidates.clear();
7163
7161
  this.goalJudgeCallId = void 0;
@@ -7215,7 +7213,11 @@ var SessionEventHandler = class {
7215
7213
  this.renderedMcpServerStatusKeys.set(server.name, mcpServerStatusKey(server));
7216
7214
  hidden.push(server);
7217
7215
  }
7218
- if (hidden.length > 0) host.showStatus(formatMcpStartupStatusSummary(hidden, visible.length), host.state.theme.colors.textMuted);
7216
+ if (hidden.length > 0) {
7217
+ const summary = formatMcpStartupStatusSummary(hidden, visible.length);
7218
+ if (hidden.some((server) => server.status === "failed" || server.status === "needs-auth")) host.showStatus(summary, host.state.theme.colors.textMuted);
7219
+ else host.showMcpActivity?.(summary, host.state.theme.colors.textMuted);
7220
+ }
7219
7221
  }
7220
7222
  handleEvent(event, sendQueued) {
7221
7223
  if (stampsActivity(event)) this.host.state.lastActivityAt = Date.now();
@@ -7325,17 +7327,6 @@ var SessionEventHandler = class {
7325
7327
  default: break;
7326
7328
  }
7327
7329
  }
7328
- stopAllMcpServerStatusSpinners() {
7329
- const { state } = this.host;
7330
- const children = state.transcriptContainer.children;
7331
- for (const spinner of this.mcpServerStatusSpinners.values()) {
7332
- spinner.stop();
7333
- const idx = children.indexOf(spinner);
7334
- if (idx >= 0) children.splice(idx, 1);
7335
- }
7336
- if (this.mcpServerStatusSpinners.size > 0) state.transcriptContainer.invalidate();
7337
- this.mcpServerStatusSpinners.clear();
7338
- }
7339
7330
  /** Read-only snapshot of the sidebar subagent slots (8 default types +
7340
7331
  * extras in spawn order). Consumed by the sidebar data provider. */
7341
7332
  getSubagentSlots() {
@@ -7877,6 +7868,12 @@ var SessionEventHandler = class {
7877
7868
  handleSessionWarning(event) {
7878
7869
  this.host.showStatus(t("handler.warning_prefix", { message: event.message }), this.host.state.theme.colors.warning);
7879
7870
  }
7871
+ /**
7872
+ * MCP server status goes to the status row above the editor — a transient
7873
+ * notice with its own TTL (same design as the collaboration ticker), not a
7874
+ * permanent transcript row. Failures / auth requests stay in the transcript
7875
+ * because they need user action and must not vanish after a few seconds.
7876
+ */
7880
7877
  renderMcpServerStatus(server) {
7881
7878
  const { state } = this.host;
7882
7879
  const key = mcpServerStatusKey(server);
@@ -7886,63 +7883,29 @@ var SessionEventHandler = class {
7886
7883
  switch (server.status) {
7887
7884
  case "connected": {
7888
7885
  const toolStr = `${server.toolCount} tool${server.toolCount === 1 ? "" : "s"}`;
7889
- const message = `MCP server "${server.name}" connected · ${toolStr} (${server.transport})`;
7890
- this.finalizeMcpServerStatusRow(server.name, message, colors.success);
7886
+ this.host.showMcpActivity?.(`MCP ${server.name} · ${toolStr}`, colors.success);
7891
7887
  return;
7892
7888
  }
7889
+ case "pending":
7890
+ this.host.showMcpActivity?.(t("handler.mcp_server_connecting", { name: server.name }), colors.textMuted);
7891
+ return;
7892
+ case "disabled":
7893
+ this.host.showMcpActivity?.(t("handler.mcp_server_disabled", { name: server.name }), colors.textMuted);
7894
+ return;
7893
7895
  case "failed": {
7894
7896
  const message = t("handler.mcp_server_failed", {
7895
7897
  name: server.name,
7896
7898
  error: server.error !== void 0 ? `: ${server.error}` : ""
7897
7899
  });
7898
- this.finalizeMcpServerStatusRow(server.name, message, colors.error);
7900
+ this.host.showStatus(message, colors.error);
7899
7901
  return;
7900
7902
  }
7901
7903
  case "needs-auth": {
7902
7904
  const message = t("handler.mcp_server_needs_auth", { name: server.name });
7903
- this.finalizeMcpServerStatusRow(server.name, message, colors.warning);
7905
+ this.host.showStatus(message, colors.warning);
7904
7906
  return;
7905
7907
  }
7906
- case "disabled":
7907
- this.finalizeMcpServerStatusRow(server.name, t("handler.mcp_server_disabled", { name: server.name }), colors.textMuted);
7908
- return;
7909
- case "pending":
7910
- this.showMcpServerStatusSpinner(server.name);
7911
- return;
7912
- }
7913
- }
7914
- showMcpServerStatusSpinner(name) {
7915
- const { state } = this.host;
7916
- const label = t("handler.mcp_server_connecting", { name });
7917
- const existing = this.mcpServerStatusSpinners.get(name);
7918
- if (existing !== void 0) {
7919
- existing.setLabel(label);
7920
- return;
7921
- }
7922
- const tint = (s) => chalk.hex(state.theme.colors.textMuted)(s);
7923
- const spinner = new MoonLoader(state.ui, tint, label);
7924
- state.transcriptContainer.addChild(spinner);
7925
- this.mcpServerStatusSpinners.set(name, spinner);
7926
- state.ui.requestRender();
7927
- }
7928
- finalizeMcpServerStatusRow(name, message, color) {
7929
- const { state } = this.host;
7930
- const spinner = this.mcpServerStatusSpinners.get(name);
7931
- if (spinner === void 0) {
7932
- this.host.showStatus(message, color);
7933
- return;
7934
7908
  }
7935
- spinner.stop();
7936
- const container = state.transcriptContainer;
7937
- const children = container.children;
7938
- const idx = children.indexOf(spinner);
7939
- if (idx >= 0) {
7940
- children.splice(idx, 1);
7941
- container.addChild(new StatusMessageComponent(message, state.theme.colors, color));
7942
- container.invalidate();
7943
- } else container.addChild(new StatusMessageComponent(message, state.theme.colors, color));
7944
- this.mcpServerStatusSpinners.delete(name);
7945
- state.ui.requestRender();
7946
7909
  }
7947
7910
  handleSkillActivated(event) {
7948
7911
  if (this.renderedSkillActivationIds.has(event.activationId)) return;
@@ -8085,7 +8048,7 @@ var SessionEventHandler = class {
8085
8048
  * candidate was detected. */
8086
8049
  promptSkillCandidate(session, name, purpose) {
8087
8050
  if (this.host.state.appState.model.trim().length === 0) return;
8088
- const request = `检测到可复用过程「${name}」${purpose ? `(${purpose})` : ""}。请用 AskUserQuestion 工具询问用户是否将其保存为可复用技能(选项:生成 / 忽略)。用户选择「生成」后,用 MakeSkillPlanTool 生成该技能;选择「忽略」则直接说明已跳过。`;
8051
+ const request = `检测到可复用过程「${name}」${purpose ? `(${purpose})` : ""}。请用 AskUserQuestion 工具询问用户是否将其保存为可复用技能(选项:生成 / 忽略)。用户选择「生成」后,用 MakeSkillPlanTool 生成该技能,再用 MakeSkillApply 落盘;落盘后把 plan.verification.instructions 原样告诉用户,并说明这是装完后要跑的触发检查。选择「忽略」则直接说明已跳过。`;
8089
8052
  session.prompt(request).catch(() => {
8090
8053
  this.host.showStatus(`检测到可复用过程「${name}」,但询问失败。可稍后手动处理。`, this.host.state.theme.colors.warning);
8091
8054
  });
@@ -11704,7 +11667,6 @@ var TranscriptController = class TranscriptController {
11704
11667
  const { state } = this.host;
11705
11668
  this.welcomeComponent?.stopBreathing();
11706
11669
  const welcome = new WelcomeComponent(state.appState, state.theme.colors, state.ui);
11707
- welcome.borderTitle = "Scream Code";
11708
11670
  this.welcomeComponent = welcome;
11709
11671
  if (state.editor.hasFirstInputFired()) welcome.stopBreathing();
11710
11672
  state.transcriptContainer.addChild(welcome);
@@ -11894,14 +11856,14 @@ var GutterContainer = class extends Container {
11894
11856
  * string and truncated to the available width.
11895
11857
  */
11896
11858
  /**
11897
- * Single-line row: `<wave> <label> <reminder> <activity>`, empty parts
11898
- * omitted.
11859
+ * Single-line row: `<wave> <label> <reminder> <activity> <notice>`,
11860
+ * empty parts omitted.
11899
11861
  *
11900
11862
  * HStack cannot produce this layout: pi-tui's Text.render pads every line to
11901
11863
  * the full row width, so each child's intrinsic width equals the full width
11902
11864
  * and HStack's shrink distribution pushes later segments far to the right.
11903
11865
  * Composing the line manually from the loader's unpadded frame text keeps the
11904
- * segments adjacent, and it re-reads the frame (and both chips) on every
11866
+ * segments adjacent, and it re-reads the frame (and every chip) on every
11905
11867
  * render so the wave keeps animating and the tickers update in place.
11906
11868
  */
11907
11869
  var StatusLine = class {
@@ -11910,27 +11872,50 @@ var StatusLine = class {
11910
11872
  labelColor;
11911
11873
  reminder;
11912
11874
  activity;
11875
+ notice;
11913
11876
  labelCollapsesOnChip;
11914
- constructor(wave, label, labelColor, reminder, activity, labelCollapsesOnChip = false) {
11877
+ constructor(wave, label, labelColor, reminder, activity, notice, labelCollapsesOnChip = false) {
11915
11878
  this.wave = wave;
11916
11879
  this.label = label;
11917
11880
  this.labelColor = labelColor;
11918
11881
  this.reminder = reminder;
11919
11882
  this.activity = activity;
11883
+ this.notice = notice;
11920
11884
  this.labelCollapsesOnChip = labelCollapsesOnChip;
11921
11885
  }
11922
11886
  render(width) {
11923
11887
  const minWidth = Math.max(1, width);
11924
11888
  const reminder = this.reminder?.() ?? null;
11925
11889
  const activity = this.activity?.() ?? null;
11890
+ const notice = this.notice?.() ?? null;
11926
11891
  const showLabel = !(this.labelCollapsesOnChip && (reminder !== null || activity !== null));
11927
- const segments = [];
11928
- if (this.wave !== void 0) segments.push(this.wave.getFrameText());
11929
- if (showLabel && this.label.length > 0) segments.push(this.labelColor === void 0 ? this.label : chalk.hex(this.labelColor)(this.label));
11930
- for (const chip of [reminder, activity]) {
11931
- if (chip === null) continue;
11932
- segments.push(chip.color === void 0 ? chip.text : chalk.hex(chip.color)(chip.text));
11892
+ const waveText = this.wave !== void 0 ? this.wave.getFrameText() : null;
11893
+ const paintChip = (chip) => {
11894
+ if (chip === null) return null;
11895
+ return chip.color === void 0 ? chip.text : chalk.hex(chip.color)(chip.text);
11896
+ };
11897
+ const reminderText = paintChip(reminder);
11898
+ const activityText = paintChip(activity);
11899
+ const noticeText = paintChip(notice);
11900
+ let labelText = showLabel && this.label.length > 0 ? this.labelColor === void 0 ? this.label : chalk.hex(this.labelColor)(this.label) : null;
11901
+ if (labelText !== null && noticeText !== null) {
11902
+ const fixedSegments = [
11903
+ waveText,
11904
+ reminderText,
11905
+ activityText,
11906
+ noticeText
11907
+ ].filter((segment) => segment !== null);
11908
+ const room = minWidth - (1 + fixedSegments.reduce((total, segment) => total + visibleWidth(segment), 0) + fixedSegments.length * 2);
11909
+ labelText = room >= 2 ? truncateToWidth(labelText, room, "…") : null;
11933
11910
  }
11911
+ const segments = [];
11912
+ if (waveText !== null) segments.push(waveText);
11913
+ if (labelText !== null && labelText.length > 0) segments.push(labelText);
11914
+ for (const chipText of [
11915
+ reminderText,
11916
+ activityText,
11917
+ noticeText
11918
+ ]) if (chipText !== null) segments.push(chipText);
11934
11919
  if (segments.length === 0) return [];
11935
11920
  if (this.wave !== void 0 && segments.length === 1) return [truncateToWidth(segments[0], minWidth)];
11936
11921
  return [truncateToWidth(` ${segments.join(" ")}`, minWidth)];
@@ -11959,11 +11944,11 @@ var StatusBarPaneComponent = class extends Container {
11959
11944
  update(options) {
11960
11945
  this.clear();
11961
11946
  if (options.mode === "idle") {
11962
- if (options.label.length > 0 || options.reminder !== void 0 || options.activity !== void 0) this.addChild(new StatusLine(void 0, options.label, options.labelColor, options.reminder, options.activity, true));
11947
+ if (options.label.length > 0 || options.reminder !== void 0 || options.activity !== void 0 || options.notice !== void 0) this.addChild(new StatusLine(void 0, options.label, options.labelColor, options.reminder, options.activity, options.notice, true));
11963
11948
  return;
11964
11949
  }
11965
11950
  if (options.pulseWave !== void 0) {
11966
- this.addChild(new StatusLine(options.pulseWave, options.label, options.labelColor, options.reminder, options.activity));
11951
+ this.addChild(new StatusLine(options.pulseWave, options.label, options.labelColor, options.reminder, options.activity, options.notice));
11967
11952
  return;
11968
11953
  }
11969
11954
  if (options.label.length > 0) {
@@ -13087,6 +13072,11 @@ const COLLAB_ACTIVITY_TTL_MS = 8e3;
13087
13072
  /** How long a scheduled-task reminder stays: longer than the collaboration
13088
13073
  * chip because a cron fire is time-sensitive and must not slip by. */
13089
13074
  const REMINDER_ACTIVITY_TTL_MS = 1e4;
13075
+ /** How long an MCP server notice stays on the status bar (own slot, transient
13076
+ * by design — startup connect chatter must not occupy the transcript).
13077
+ * Short on purpose: the notice appears once loading finishes and clears
13078
+ * quickly instead of parking on the row. */
13079
+ const MCP_ACTIVITY_TTL_MS = 3e3;
13090
13080
  /** Footer git badge freshness window; the deferred read refreshes past it. */
13091
13081
  const GIT_DIFF_TTL_MS = 15e3;
13092
13082
  /** Window after a command-driven line write during which the poll stands down. */
@@ -13123,6 +13113,11 @@ var LifecycleController = class LifecycleController {
13123
13113
  * a collaboration request can never evict a fired reminder. */
13124
13114
  reminderActivity = null;
13125
13115
  reminderTimer;
13116
+ /** Single-slot MCP server notice (connect / connecting / disabled). Own slot
13117
+ * for the same reason: a burst of server statuses must never evict a
13118
+ * collaboration request or a fired reminder. */
13119
+ mcpActivity = null;
13120
+ mcpTimer;
13126
13121
  /** Sum all four token buckets into the session's total token consumption. */
13127
13122
  static sumTokens(usage) {
13128
13123
  return usage.inputOther + usage.inputCacheRead + usage.inputCacheCreation + usage.output;
@@ -13591,7 +13586,8 @@ var LifecycleController = class LifecycleController {
13591
13586
  labelColor: state.theme.colors.warning,
13592
13587
  pulseWave: loader,
13593
13588
  reminder: () => this.getReminderActivity(),
13594
- activity: () => this.getCollabActivity()
13589
+ activity: () => this.getCollabActivity(),
13590
+ notice: () => this.getMcpActivity()
13595
13591
  }));
13596
13592
  }
13597
13593
  break;
@@ -13604,7 +13600,8 @@ var LifecycleController = class LifecycleController {
13604
13600
  label: tip === void 0 ? "" : composeTipLabel(t(tip.i18nKey), tip, state.theme.colors.primary),
13605
13601
  labelColor: state.theme.colors.textDim,
13606
13602
  reminder: () => this.getReminderActivity(),
13607
- activity: () => this.getCollabActivity()
13603
+ activity: () => this.getCollabActivity(),
13604
+ notice: () => this.getMcpActivity()
13608
13605
  }));
13609
13606
  if (tip !== void 0) this.startTipRotation();
13610
13607
  break;
@@ -13690,6 +13687,29 @@ var LifecycleController = class LifecycleController {
13690
13687
  getReminderActivity() {
13691
13688
  return this.reminderActivity;
13692
13689
  }
13690
+ /**
13691
+ * Shows an MCP server notice on the status row (connected / connecting /
13692
+ * disabled). Single slot, newest wins, expires after `MCP_ACTIVITY_TTL_MS`;
13693
+ * the row reads it live, so no rebuild (and no wave reset) is involved.
13694
+ * The colour is chosen by the caller (success / muted).
13695
+ */
13696
+ showMcpActivity(text, color) {
13697
+ this.mcpActivity = {
13698
+ text,
13699
+ color
13700
+ };
13701
+ if (this.mcpTimer !== void 0) clearTimeout(this.mcpTimer);
13702
+ this.mcpTimer = setTimeout(() => {
13703
+ this.mcpTimer = void 0;
13704
+ this.mcpActivity = null;
13705
+ this.host.state.ui?.requestRender();
13706
+ }, MCP_ACTIVITY_TTL_MS);
13707
+ this.host.state.ui?.requestRender();
13708
+ }
13709
+ /** Live getter consumed by the status row on every render. */
13710
+ getMcpActivity() {
13711
+ return this.mcpActivity;
13712
+ }
13693
13713
  /** Drops every transient chip (session switch, shutdown). */
13694
13714
  clearStatusActivity() {
13695
13715
  if (this.collabTimer !== void 0) {
@@ -13702,6 +13722,11 @@ var LifecycleController = class LifecycleController {
13702
13722
  this.reminderTimer = void 0;
13703
13723
  }
13704
13724
  this.reminderActivity = null;
13725
+ if (this.mcpTimer !== void 0) {
13726
+ clearTimeout(this.mcpTimer);
13727
+ this.mcpTimer = void 0;
13728
+ }
13729
+ this.mcpActivity = null;
13705
13730
  }
13706
13731
  /**
13707
13732
  * Stops every animation this controller owns. Called from the shutdown path:
@@ -19889,7 +19914,6 @@ var ScreamTUI = class {
19889
19914
  clearRuntimeMarker(getDataDir());
19890
19915
  await this.closeSession();
19891
19916
  await this.harness.close();
19892
- this.sessionEventHandler.stopAllMcpServerStatusSpinners();
19893
19917
  this.state.ui.stop();
19894
19918
  if (this.onExit) await this.onExit(exitCode);
19895
19919
  }
@@ -20066,6 +20090,10 @@ var ScreamTUI = class {
20066
20090
  showReminderActivity(text, tone) {
20067
20091
  this.lifecycleController.showReminderActivity(text, tone);
20068
20092
  }
20093
+ /** MCP server notice above the editor (connecting / connected / disabled). */
20094
+ showMcpActivity(text, color) {
20095
+ this.lifecycleController.showMcpActivity(text, color);
20096
+ }
20069
20097
  /** Drops every transient chip on the status row (session switch). */
20070
20098
  clearStatusActivity() {
20071
20099
  this.lifecycleController.clearStatusActivity();
@@ -20219,7 +20247,7 @@ var ScreamTUI = class {
20219
20247
  const card = new OnboardingCardComponent({
20220
20248
  colors: this.state.theme.colors,
20221
20249
  onConfigure: () => {
20222
- import("./dispatch-d_R8-8sn.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
20250
+ import("./dispatch-DD8Vu4Qc.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
20223
20251
  this.restoreEditor();
20224
20252
  onDone?.();
20225
20253
  });
@@ -20281,7 +20309,6 @@ var ScreamTUI = class {
20281
20309
  this.mountEditorReplacement(card);
20282
20310
  }
20283
20311
  clearTranscriptAndRedraw() {
20284
- this.sessionEventHandler.stopAllMcpServerStatusSpinners();
20285
20312
  clearGoalState();
20286
20313
  clearInfoPanelState(this.state);
20287
20314
  clearEvalPanelState(this.state);
@@ -3,5 +3,5 @@ import { fileURLToPath as __cjsShimFileURLToPath } from 'node:url';
3
3
  import { dirname as __cjsShimDirname } from 'node:path';
4
4
  const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
- import { Qt as handleConnectCommand } from "./dispatch-BiOeRj_C.mjs";
6
+ import { Qt as handleConnectCommand } from "./dispatch-DMntc47e.mjs";
7
7
  export { handleConnectCommand };