scream-code 0.13.4 → 0.13.6

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.
@@ -4,8 +4,8 @@ import { dirname as __cjsShimDirname } from 'node:path';
4
4
  const __filename = __cjsShimFileURLToPath(import.meta.url);
5
5
  const __dirname = __cjsShimDirname(__filename);
6
6
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
7
- import { $ as toTerminalHyperlink, $t as parseStreamingArgs, A as highlightLines, An as CLI_USER_AGENT_PRODUCT, At as ENABLE_TERMINAL_THEME_REPORTING, B as AssistantMessageComponent, Bn as log, Bt as isBusy, C as UserMessageComponent, Cn as detectShellEnvironment, Ct as contrastTextHex, D as ToolCallComponent, Dn as detectInstallSource, Dt as DISABLE_TERMINAL_FOCUS_REPORTING, E as toggleEmptySessionHint, En as getLogDir, Et as parseOsc11BackgroundTheme, F as getSharedSpeedTracker, Fn as ScreamHarness, Ft as QUERY_TERMINAL_THEME, G as resetBreathingClock, Gn as SCREAM_ERROR_INFO, H as WelcomeComponent, Hn as isScreamError, Ht as FooterComponent, I as SkillActivationComponent, It as TERMINAL_FOCUS_IN, Jt as STATUS_BULLET, K as clearGoalState, L as ReadGroupComponent, Ln as resolveScreamHome, Lt as TERMINAL_FOCUS_OUT, M as CachedContainer, Mn as DEFAULT_CATALOG_URL, Mt as OSC11_RESPONSE, N as ThinkingComponent, Nn as fetchCatalog, Nt as OSC11_RESPONSE_PREFIX, O as renderDiffLines, On as CLI_COMMAND_NAME, Ot as DISABLE_TERMINAL_THEME_REPORTING, P as estimateTokens, Pn as saveCatalogCache, Pt as OSC11_RESPONSE_PREFIX_NO_ESC, Qt as isTodoItemShape, R as parseReadGroupOutput, Rn as MemoryMemoStore, Rt as TERMINAL_THEME_DARK, Sn as saveTuiConfig, St as createThemeStyles, T as isTurnElapsedEnabled, Tn as getInputHistoryFile, Tt as detectTerminalTheme, U as BREATHE_CYCLE_MS, Un as isOrphanedToolCallError, V as AgentGroupComponent, Vn as resolveGlobalLogPath, Vt as isStreaming, W as getBreathingFrame, Wn as ErrorCodes, Xt as argsRecord, Yt as appendStreamingArgsPreview, Zt as formatErrorMessage, _ as readUpdateCache, _n as PIXEL_PULSE_FRAMES, an as MAIN_AGENT_ID, at as handleFusionPlanCommand, bn as TuiLikePreferencesSchema, bt as createEditorTheme, c as isPlanExpandable, cn as getCtrlCHint, dn as getNoActiveSessionMessage, en as serializeToolResultOutput, et as changeThinkingLevel, fn as buildSkillSlashCommands, g as refreshUpdateCache, gn as setExperimentalFlags, gt as clearInfoPanelState, h as selectUpdateTarget, hn as isExperimentalFlagEnabled, ht as supportsBalance, i as buildRoleAdditionalText, in as EXIT_CONFIRM_WINDOW_MS, j as langFromPath, jn as PRODUCT_NAME, jt as OSC11_QUERY, k as renderDiffLinesClustered, kn as CLI_UI_MODE, kt as ENABLE_TERMINAL_FOCUS_REPORTING, l as MoonLoader, ln as getCtrlDHint, mn as sortSlashCommands, mt as refreshProviderBalance, n as clearEvalPanelState, nn as truncateErrorMessage, o as disposeChildren, on as SESSION_TIPS, pn as BUILTIN_SLASH_COMMANDS, q as refineGoal, qt as printableChar, r as openUrl, rn as EMPTY_SESSION_HINT_URL, s as hasDispose, sn as TIP_ROTATION_INTERVAL_MS, st as handlePlanCommand, t as dispatchInput, tn as stringValue, tt as getModelCycleLevel, u as formatMemoryMemoForInjection, un as getLlmNotSetMessage, v as appendJsonlLine, vn as PULSE_WAVE_FRAMES, w as isEmptySessionHintDismissed, wn as getDataDir, wt as getColorPalette, x as getDaemonInstructions, xn as loadTuiConfig, xt as createMarkdownTheme, y as readJsonlFile, yn as TuiConfigParseError, yt as resolveThemeSync, z as BackgroundAgentStatusComponent, zn as flushDiagnosticLogs, zt as TERMINAL_THEME_LIGHT } from "./dispatch-Dk8_Wqp6.mjs";
8
- import { a as setLocale, o as t } from "./text-input-dialog-ClcJf9pu.mjs";
7
+ import { $ as toTerminalHyperlink, $t as parseStreamingArgs, A as highlightLines, An as CLI_UI_MODE, At as ENABLE_TERMINAL_THEME_REPORTING, B as AssistantMessageComponent, Bn as flushDiagnosticLogs, Bt as isBusy, C as UserMessageComponent, Cn as saveTuiConfig, Ct as contrastTextHex, D as ToolCallComponent, Dn as getLogDir, Dt as DISABLE_TERMINAL_FOCUS_REPORTING, E as toggleEmptySessionHint, En as getInputHistoryFile, Et as parseOsc11BackgroundTheme, F as getSharedSpeedTracker, Fn as saveCatalogCache, Ft as QUERY_TERMINAL_THEME, G as resetBreathingClock, Gn as ErrorCodes, H as WelcomeComponent, Hn as resolveGlobalLogPath, Ht as FooterComponent, I as SkillActivationComponent, In as ScreamHarness, It as TERMINAL_FOCUS_IN, Jt as STATUS_BULLET, K as clearGoalState, Kn as SCREAM_ERROR_INFO, L as ReadGroupComponent, Lt as TERMINAL_FOCUS_OUT, M as CachedContainer, Mn as PRODUCT_NAME, Mt as OSC11_RESPONSE, N as ThinkingComponent, Nn as DEFAULT_CATALOG_URL, Nt as OSC11_RESPONSE_PREFIX, O as renderDiffLines, On as detectInstallSource, Ot as DISABLE_TERMINAL_THEME_REPORTING, P as estimateTokens, Pn as fetchCatalog, Pt as OSC11_RESPONSE_PREFIX_NO_ESC, Qt as isTodoItemShape, R as parseReadGroupOutput, Rn as resolveScreamHome, Rt as TERMINAL_THEME_DARK, Sn as loadTuiConfig, St as createThemeStyles, T as isTurnElapsedEnabled, Tn as getDataDir, Tt as detectTerminalTheme, U as BREATHE_CYCLE_MS, Un as isScreamError, V as AgentGroupComponent, Vn as log, Vt as isStreaming, W as getBreathingFrame, Wn as isOrphanedToolCallError, Xt as argsRecord, Yt as appendStreamingArgsPreview, Zt as formatErrorMessage, _ as readUpdateCache, _n as setExperimentalFlags, an as EXIT_CONFIRM_WINDOW_MS, at as handleFusionPlanCommand, bn as TuiConfigParseError, bt as createEditorTheme, c as isPlanExpandable, cn as TIP_ROTATION_INTERVAL_MS, dn as getLlmNotSetMessage, en as serializeToolResultOutput, et as changeThinkingLevel, fn as getNoActiveSessionMessage, g as refreshUpdateCache, gn as isExperimentalFlagEnabled, gt as clearInfoPanelState, h as selectUpdateTarget, hn as sortSlashCommands, ht as supportsBalance, i as buildRoleAdditionalText, in as EMPTY_SESSION_HINT_URL, j as langFromPath, jn as CLI_USER_AGENT_PRODUCT, jt as OSC11_QUERY, k as renderDiffLinesClustered, kn as CLI_COMMAND_NAME, kt as ENABLE_TERMINAL_FOCUS_REPORTING, l as MoonLoader, ln as getCtrlCHint, mn as BUILTIN_SLASH_COMMANDS, mt as refreshProviderBalance, n as clearEvalPanelState, nn as truncateErrorMessage, o as disposeChildren, on as MAIN_AGENT_ID, pn as buildSkillSlashCommands, q as refineGoal, qt as printableChar, r as openUrl, rn as CHARS_PER_TOKEN, s as hasDispose, sn as SESSION_TIPS, st as handlePlanCommand, t as dispatchInput, tn as stringValue, tt as getModelCycleLevel, u as formatMemoryMemoForInjection, un as getCtrlDHint, v as appendJsonlLine, vn as PIXEL_PULSE_FRAMES, w as isEmptySessionHintDismissed, wn as detectShellEnvironment, wt as getColorPalette, x as getDaemonInstructions, xn as TuiLikePreferencesSchema, xt as createMarkdownTheme, y as readJsonlFile, yn as PULSE_WAVE_FRAMES, yt as resolveThemeSync, z as BackgroundAgentStatusComponent, zn as MemoryMemoStore, zt as TERMINAL_THEME_LIGHT } from "./dispatch-CEemtjRD.mjs";
8
+ import { a as setLocale, o as t } from "./text-input-dialog-DstXBOl9.mjs";
9
9
  import { createRequire } from "node:module";
10
10
  import { randomUUID } from "node:crypto";
11
11
  import { access, mkdir, mkdtemp, readFile, readdir, realpath, rm, unlink, writeFile } from "node:fs/promises";
@@ -30,7 +30,7 @@ function optionalBuildString(value) {
30
30
  return typeof value === "string" && value.length > 0 ? value : void 0;
31
31
  }
32
32
  const SCREAM_BUILD_INFO = {
33
- version: optionalBuildString("0.13.4"),
33
+ version: optionalBuildString("0.13.6"),
34
34
  channel: optionalBuildString(""),
35
35
  commit: optionalBuildString(""),
36
36
  buildTarget: optionalBuildString("darwin-arm64")
@@ -1868,6 +1868,17 @@ var EditorKeyboardController = class {
1868
1868
  function replaceTabs(text, tabWidth = 4) {
1869
1869
  return text.replaceAll(" ", " ".repeat(tabWidth));
1870
1870
  }
1871
+ /**
1872
+ * Strip terminal control characters from untrusted shell output before it is
1873
+ * rendered inside a framed pane. Carriage returns (progress-bar redraws) and
1874
+ * ANSI escape sequences (cursor moves, screen clears, SGR color codes, OSC
1875
+ * title/OSC 52 clipboard sequences, charset selection) would otherwise disrupt
1876
+ * the terminal borders or let task output inject escape sequences. All
1877
+ * printable text is preserved.
1878
+ */
1879
+ function sanitizeShellOutput(output) {
1880
+ return output.replaceAll("\r", "").replaceAll(/\u001B\[[0-?]*[ -/]*[@-~]/g, "").replaceAll(/\u001B\][^\u0007\u001B]*(?:\u0007|\u001B\\)/g, "").replaceAll(/\u001B[P^_][^\u0007\u001B]*(?:\u0007|\u001B\\)/g, "").replaceAll(/\u001B[()][0-9A-Za-z]/g, "").replaceAll(/\u001B[=>78DEFHMc]/g, "");
1881
+ }
1871
1882
  //#endregion
1872
1883
  //#region src/tui/components/messages/status-message.ts
1873
1884
  var StatusMessageComponent = class extends Container {
@@ -3928,6 +3939,13 @@ var StreamingUIController = class {
3928
3939
  turnStartAt = 0;
3929
3940
  _currentStep = 0;
3930
3941
  _assistantDraft = "";
3942
+ /**
3943
+ * Chars of `_assistantDraft` already shown on screen. The smooth renderer
3944
+ * advances this by a per-frame budget (clamped to the arrival rate), so
3945
+ * bursts are spread across frames instead of rendered in one block and slow
3946
+ * streams keep up. Reset alongside the draft.
3947
+ */
3948
+ _shownAssistantLength = 0;
3931
3949
  _thinkingDraft = "";
3932
3950
  lastDeltaAt;
3933
3951
  _thinkingEntry = void 0;
@@ -4001,6 +4019,7 @@ var StreamingUIController = class {
4001
4019
  }
4002
4020
  clearAssistantDraft() {
4003
4021
  this._assistantDraft = "";
4022
+ this._shownAssistantLength = 0;
4004
4023
  }
4005
4024
  getActiveToolCall(id) {
4006
4025
  return this._activeToolCalls.get(id);
@@ -4183,7 +4202,7 @@ var StreamingUIController = class {
4183
4202
  }
4184
4203
  }
4185
4204
  hasPending() {
4186
- return this.pendingAssistantFlush || this.pendingThinkingFlush || this.pendingToolCallFlushIds.size > 0;
4205
+ return this.pendingAssistantFlush || this.pendingThinkingFlush || this.pendingToolCallFlushIds.size > 0 || this._shownAssistantLength < this._assistantDraft.length;
4187
4206
  }
4188
4207
  clearFlushTimer() {
4189
4208
  if (this.flushTimer === void 0) return;
@@ -4200,10 +4219,10 @@ var StreamingUIController = class {
4200
4219
  this.pendingThinkingFlush = false;
4201
4220
  this.pendingToolCallFlushIds.clear();
4202
4221
  }
4203
- scheduleFlush() {
4222
+ scheduleFlush(frameMs = 50) {
4204
4223
  if (!this.hasPending()) return;
4205
4224
  if (this.flushTimer !== void 0) return;
4206
- const delay = this.lastFlushAt === void 0 ? 0 : Math.max(0, 50 - (Date.now() - this.lastFlushAt));
4225
+ const delay = this.lastFlushAt === void 0 ? 0 : Math.max(0, frameMs - (Date.now() - this.lastFlushAt));
4207
4226
  this.flushTimer = setTimeout(() => {
4208
4227
  this.flushTimer = void 0;
4209
4228
  this.flush();
@@ -4223,8 +4242,26 @@ var StreamingUIController = class {
4223
4242
  this.pendingAssistantFlush = false;
4224
4243
  this.pendingToolCallFlushIds.clear();
4225
4244
  if (shouldFlushThinking && this._thinkingDraft.length > 0) this.onThinkingUpdate(this._thinkingDraft);
4226
- if (shouldFlushAssistant) this.onStreamingTextUpdate(this._assistantDraft);
4245
+ if (shouldFlushAssistant || this._shownAssistantLength < this._assistantDraft.length) {
4246
+ const shown = this.advanceAssistantShown();
4247
+ if (shown > 0) this.onStreamingTextUpdate(this._assistantDraft.slice(0, shown));
4248
+ }
4227
4249
  for (const id of toolCallIds) this.flushToolCallPreview(id);
4250
+ if (this._shownAssistantLength < this._assistantDraft.length) this.scheduleFlush(50);
4251
+ }
4252
+ /**
4253
+ * Advance the smooth-render cursor by this frame's character budget.
4254
+ * Budget clamps to the measured arrival rate (fast models keep up, slow
4255
+ * models never fall behind) with a floor so the stream never freezes and a
4256
+ * ceiling so one oversized burst is spread across frames.
4257
+ */
4258
+ advanceAssistantShown() {
4259
+ const draft = this._assistantDraft;
4260
+ if (this._shownAssistantLength >= draft.length) return this._shownAssistantLength;
4261
+ const measured = getSharedSpeedTracker().getSpeed();
4262
+ const budget = Math.min(25, Math.max(1, Math.ceil((measured > 0 ? measured : 50) * (50 / 1e3) * CHARS_PER_TOKEN)));
4263
+ this._shownAssistantLength = Math.min(draft.length, this._shownAssistantLength + budget);
4264
+ return this._shownAssistantLength;
4228
4265
  }
4229
4266
  markAssistantDirty() {
4230
4267
  this.pendingAssistantFlush = true;
@@ -4238,17 +4275,21 @@ var StreamingUIController = class {
4238
4275
  this.onThinkingEnd();
4239
4276
  }
4240
4277
  finalizeAssistantStream() {
4278
+ if (this._shownAssistantLength < this._assistantDraft.length) this._shownAssistantLength = this._assistantDraft.length;
4279
+ this.pendingAssistantFlush = true;
4241
4280
  this.flushNow();
4242
4281
  if (this._streamingBlock !== null) this.onStreamingTextEnd();
4243
4282
  this._assistantDraft = "";
4283
+ this._shownAssistantLength = 0;
4244
4284
  this.host.updateActivityPane();
4245
4285
  this.host.state.ui.requestRender();
4246
4286
  }
4247
4287
  resetLiveText() {
4248
4288
  this.pendingAssistantFlush = false;
4249
4289
  this.pendingThinkingFlush = false;
4250
- this.clearFlushTimerIfIdle();
4251
4290
  this._assistantDraft = "";
4291
+ this._shownAssistantLength = 0;
4292
+ this.clearFlushTimerIfIdle();
4252
4293
  this._streamingBlock = null;
4253
4294
  this._thinkingDraft = "";
4254
4295
  this.lastDeltaAt = void 0;
@@ -4788,7 +4829,8 @@ var TaskOutputViewer = class extends Container {
4788
4829
  this.invalidate();
4789
4830
  }
4790
4831
  splitOutput(output) {
4791
- return (output.length > 0 ? output : t("taskviewer.no_output")).split("\n");
4832
+ const sanitized = sanitizeShellOutput(output);
4833
+ return (sanitized.length > 0 ? sanitized : t("taskviewer.no_output")).split("\n");
4792
4834
  }
4793
4835
  handleInput(data) {
4794
4836
  const visible = this.viewableRows();
@@ -5296,7 +5338,7 @@ var TasksBrowserApp = class extends Container {
5296
5338
  let body;
5297
5339
  if (this.props.tailLoading) body = "[loading…]";
5298
5340
  else if (this.props.tailOutput === void 0 || this.props.tailOutput.length === 0) body = "[no output captured]";
5299
- else body = this.props.tailOutput;
5341
+ else body = sanitizeShellOutput(this.props.tailOutput);
5300
5342
  const styled = body.split("\n").slice(-innerHeight).map((line) => chalk.hex(colors.textDim)(line));
5301
5343
  while (styled.length < innerHeight) styled.push("");
5302
5344
  return this.renderFrame("Preview Output", styled, width, height);
@@ -12150,7 +12192,7 @@ var ScreamTUI = class {
12150
12192
  const card = new OnboardingCardComponent({
12151
12193
  colors: this.state.theme.colors,
12152
12194
  onConfigure: () => {
12153
- import("./dispatch-BKrBb5IE.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
12195
+ import("./dispatch-BlGMsyFT.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
12154
12196
  this.restoreEditor();
12155
12197
  });
12156
12198
  },
@@ -14672,6 +14714,7 @@ var WebSession = class {
14672
14714
  const messages = [];
14673
14715
  let currentAssistant = null;
14674
14716
  let userIndex = 0;
14717
+ let turnCount = 0;
14675
14718
  const flushUserMessagesBefore = (seq) => {
14676
14719
  while (userIndex < this.userMessages.length) {
14677
14720
  const item = this.userMessages[userIndex];
@@ -14684,23 +14727,39 @@ var WebSession = class {
14684
14727
  const event = entry.payload;
14685
14728
  flushUserMessagesBefore(entry.seq);
14686
14729
  switch (event.type) {
14687
- case "turn.started":
14688
- currentAssistant = {
14730
+ case "turn.started": {
14731
+ turnCount += 1;
14732
+ const assistant = {
14689
14733
  role: "assistant",
14690
14734
  content: "",
14691
- tools: []
14735
+ tools: [],
14736
+ turnStats: {
14737
+ turn: turnCount,
14738
+ step: 0,
14739
+ status: "done",
14740
+ firstTokenMs: null,
14741
+ llmMs: null,
14742
+ toolMs: null,
14743
+ tokens: null,
14744
+ tokensPerSec: null
14745
+ }
14692
14746
  };
14693
- messages.push(currentAssistant);
14747
+ currentAssistant = assistant;
14748
+ messages.push(assistant);
14694
14749
  break;
14750
+ }
14695
14751
  case "assistant.delta":
14696
14752
  if (currentAssistant) currentAssistant.content += event.delta;
14697
14753
  break;
14698
14754
  case "tool.call.started":
14699
- if (currentAssistant) currentAssistant.tools.push({
14700
- toolCallId: event.toolCallId,
14701
- name: event.name,
14702
- args: event.args
14703
- });
14755
+ if (currentAssistant) {
14756
+ currentAssistant.tools.push({
14757
+ toolCallId: event.toolCallId,
14758
+ name: event.name,
14759
+ args: event.args
14760
+ });
14761
+ if (currentAssistant.turnStats) currentAssistant.turnStats.step += 1;
14762
+ }
14704
14763
  break;
14705
14764
  case "tool.result":
14706
14765
  if (currentAssistant) {
@@ -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 { Gt as handleConnectCommand } from "./dispatch-Dk8_Wqp6.mjs";
6
+ import { Gt as handleConnectCommand } from "./dispatch-CEemtjRD.mjs";
7
7
  export { handleConnectCommand };