scream-code 0.13.1 → 0.13.2

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,7 +4,7 @@ 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 stringValue, A as highlightLines, An as DEFAULT_CATALOG_URL, At as ENABLE_TERMINAL_THEME_REPORTING, B as AssistantMessageComponent, Bn as isScreamError, Bt as isBusy, C as UserMessageComponent, Cn as getInputHistoryFile, Ct as contrastTextHex, D as ToolCallComponent, Dn as CLI_UI_MODE, Dt as DISABLE_TERMINAL_FOCUS_REPORTING, E as toggleEmptySessionHint, En as CLI_COMMAND_NAME, Et as parseOsc11BackgroundTheme, F as getSharedSpeedTracker, Fn as resolveScreamHome, Ft as QUERY_TERMINAL_THEME, G as resetBreathingClock, Gt as printableChar, H as WelcomeComponent, Hn as ErrorCodes, Ht as FooterComponent, I as SkillActivationComponent, In as MemoryMemoStore, It as TERMINAL_FOCUS_IN, Jt as argsRecord, K as clearGoalState, Kt as STATUS_BULLET, L as ReadGroupComponent, Ln as flushDiagnosticLogs, Lt as TERMINAL_FOCUS_OUT, M as CachedContainer, Mn as saveCatalogCache, Mt as OSC11_RESPONSE, N as ThinkingComponent, Nn as ScreamHarness, Nt as OSC11_RESPONSE_PREFIX, O as renderDiffLines, On as CLI_USER_AGENT_PRODUCT, Ot as DISABLE_TERMINAL_THEME_REPORTING, P as estimateTokens, Pt as OSC11_RESPONSE_PREFIX_NO_ESC, Qt as serializeToolResultOutput, R as parseReadGroupOutput, Rn as log, Rt as TERMINAL_THEME_DARK, Sn as getDataDir, St as createThemeStyles, T as isTurnElapsedEnabled, Tn as detectInstallSource, Tt as detectTerminalTheme, U as BREATHE_CYCLE_MS, Un as SCREAM_ERROR_INFO, V as AgentGroupComponent, Vn as isOrphanedToolCallError, Vt as isStreaming, W as getBreathingFrame, Xt as isTodoItemShape, Yt as formatErrorMessage, Zt as parseStreamingArgs, _ as readUpdateCache, _n as TuiConfigParseError, an as TIP_ROTATION_INTERVAL_MS, at as handleFusionPlanCommand, bn as saveTuiConfig, bt as createEditorTheme, c as isPlanExpandable, cn as getLlmNotSetMessage, dn as BUILTIN_SLASH_COMMANDS, en as truncateErrorMessage, et as changeThinkingLevel, fn as sortSlashCommands, g as refreshUpdateCache, gn as PULSE_WAVE_FRAMES, gt as clearInfoPanelState, h as selectUpdateTarget, hn as PIXEL_PULSE_FRAMES, ht as supportsBalance, i as buildRoleAdditionalText, in as SESSION_TIPS, j as langFromPath, jn as fetchCatalog, jt as OSC11_QUERY, k as renderDiffLinesClustered, kn as PRODUCT_NAME, kt as ENABLE_TERMINAL_FOCUS_REPORTING, l as MoonLoader, ln as getNoActiveSessionMessage, mn as setExperimentalFlags, mt as refreshProviderBalance, n as clearEvalPanelState, nn as EXIT_CONFIRM_WINDOW_MS, o as disposeChildren, on as getCtrlCHint, pn as isExperimentalFlagEnabled, q as refineGoal, qt as appendStreamingArgsPreview, r as openUrl, rn as MAIN_AGENT_ID, s as hasDispose, sn as getCtrlDHint, st as handlePlanCommand, t as dispatchInput, tn as EMPTY_SESSION_HINT_URL, tt as getModelCycleLevel, u as formatMemoryMemoForInjection, un as buildSkillSlashCommands, v as appendJsonlLine, vn as TuiLikePreferencesSchema, w as isEmptySessionHintDismissed, wn as getLogDir, wt as getColorPalette, x as getDaemonInstructions, xn as detectShellEnvironment, xt as createMarkdownTheme, y as readJsonlFile, yn as loadTuiConfig, yt as resolveThemeSync, z as BackgroundAgentStatusComponent, zn as resolveGlobalLogPath, zt as TERMINAL_THEME_LIGHT } from "./dispatch-DKrkYz9U.mjs";
7
+ import { $ as toTerminalHyperlink, $t as stringValue, A as highlightLines, An as DEFAULT_CATALOG_URL, At as ENABLE_TERMINAL_THEME_REPORTING, B as AssistantMessageComponent, Bn as isScreamError, Bt as isBusy, C as UserMessageComponent, Cn as getInputHistoryFile, Ct as contrastTextHex, D as ToolCallComponent, Dn as CLI_UI_MODE, Dt as DISABLE_TERMINAL_FOCUS_REPORTING, E as toggleEmptySessionHint, En as CLI_COMMAND_NAME, Et as parseOsc11BackgroundTheme, F as getSharedSpeedTracker, Fn as resolveScreamHome, Ft as QUERY_TERMINAL_THEME, G as resetBreathingClock, Gt as printableChar, H as WelcomeComponent, Hn as ErrorCodes, Ht as FooterComponent, I as SkillActivationComponent, In as MemoryMemoStore, It as TERMINAL_FOCUS_IN, Jt as argsRecord, K as clearGoalState, Kt as STATUS_BULLET, L as ReadGroupComponent, Ln as flushDiagnosticLogs, Lt as TERMINAL_FOCUS_OUT, M as CachedContainer, Mn as saveCatalogCache, Mt as OSC11_RESPONSE, N as ThinkingComponent, Nn as ScreamHarness, Nt as OSC11_RESPONSE_PREFIX, O as renderDiffLines, On as CLI_USER_AGENT_PRODUCT, Ot as DISABLE_TERMINAL_THEME_REPORTING, P as estimateTokens, Pt as OSC11_RESPONSE_PREFIX_NO_ESC, Qt as serializeToolResultOutput, R as parseReadGroupOutput, Rn as log, Rt as TERMINAL_THEME_DARK, Sn as getDataDir, St as createThemeStyles, T as isTurnElapsedEnabled, Tn as detectInstallSource, Tt as detectTerminalTheme, U as BREATHE_CYCLE_MS, Un as SCREAM_ERROR_INFO, V as AgentGroupComponent, Vn as isOrphanedToolCallError, Vt as isStreaming, W as getBreathingFrame, Xt as isTodoItemShape, Yt as formatErrorMessage, Zt as parseStreamingArgs, _ as readUpdateCache, _n as TuiConfigParseError, an as TIP_ROTATION_INTERVAL_MS, at as handleFusionPlanCommand, bn as saveTuiConfig, bt as createEditorTheme, c as isPlanExpandable, cn as getLlmNotSetMessage, dn as BUILTIN_SLASH_COMMANDS, en as truncateErrorMessage, et as changeThinkingLevel, fn as sortSlashCommands, g as refreshUpdateCache, gn as PULSE_WAVE_FRAMES, gt as clearInfoPanelState, h as selectUpdateTarget, hn as PIXEL_PULSE_FRAMES, ht as supportsBalance, i as buildRoleAdditionalText, in as SESSION_TIPS, j as langFromPath, jn as fetchCatalog, jt as OSC11_QUERY, k as renderDiffLinesClustered, kn as PRODUCT_NAME, kt as ENABLE_TERMINAL_FOCUS_REPORTING, l as MoonLoader, ln as getNoActiveSessionMessage, mn as setExperimentalFlags, mt as refreshProviderBalance, n as clearEvalPanelState, nn as EXIT_CONFIRM_WINDOW_MS, o as disposeChildren, on as getCtrlCHint, pn as isExperimentalFlagEnabled, q as refineGoal, qt as appendStreamingArgsPreview, r as openUrl, rn as MAIN_AGENT_ID, s as hasDispose, sn as getCtrlDHint, st as handlePlanCommand, t as dispatchInput, tn as EMPTY_SESSION_HINT_URL, tt as getModelCycleLevel, u as formatMemoryMemoForInjection, un as buildSkillSlashCommands, v as appendJsonlLine, vn as TuiLikePreferencesSchema, w as isEmptySessionHintDismissed, wn as getLogDir, wt as getColorPalette, x as getDaemonInstructions, xn as detectShellEnvironment, xt as createMarkdownTheme, y as readJsonlFile, yn as loadTuiConfig, yt as resolveThemeSync, z as BackgroundAgentStatusComponent, zn as resolveGlobalLogPath, zt as TERMINAL_THEME_LIGHT } from "./dispatch-DKaEvjOY.mjs";
8
8
  import { a as setLocale, o as t } from "./text-input-dialog-D9R3KY7O.mjs";
9
9
  import { createRequire } from "node:module";
10
10
  import { randomUUID } from "node:crypto";
@@ -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.1"),
33
+ version: optionalBuildString("0.13.2"),
34
34
  channel: optionalBuildString(""),
35
35
  commit: optionalBuildString(""),
36
36
  buildTarget: optionalBuildString("darwin-arm64")
@@ -12039,7 +12039,7 @@ var ScreamTUI = class {
12039
12039
  const card = new OnboardingCardComponent({
12040
12040
  colors: this.state.theme.colors,
12041
12041
  onConfigure: () => {
12042
- import("./dispatch-CrXPCoKZ.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
12042
+ import("./dispatch-6CtsO1av.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
12043
12043
  this.restoreEditor();
12044
12044
  });
12045
12045
  },
@@ -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 { Ut as handleConnectCommand } from "./dispatch-DKrkYz9U.mjs";
6
+ import { Ut as handleConnectCommand } from "./dispatch-DKaEvjOY.mjs";
7
7
  export { handleConnectCommand };
@@ -30,7 +30,7 @@ import { exec, execFile, execSync, spawn, spawnSync } from "node:child_process";
30
30
  import { promisify } from "node:util";
31
31
  import { DatabaseSync } from "node:sqlite";
32
32
  import * as nodeOs from "node:os";
33
- import { homedir, tmpdir } from "node:os";
33
+ import { homedir, release, tmpdir } from "node:os";
34
34
  import * as vs from "zlib";
35
35
  import Qr from "zlib";
36
36
  import { EventEmitter as EventEmitter$1 } from "node:events";
@@ -8956,6 +8956,7 @@ function convertAnthropicError(error) {
8956
8956
  }
8957
8957
  var AnthropicStreamedMessage = class {
8958
8958
  _id = null;
8959
+ _model = null;
8959
8960
  _usage = {
8960
8961
  inputOther: 0,
8961
8962
  output: 0,
@@ -8972,6 +8973,9 @@ var AnthropicStreamedMessage = class {
8972
8973
  get id() {
8973
8974
  return this._id;
8974
8975
  }
8976
+ get model() {
8977
+ return this._model;
8978
+ }
8975
8979
  get usage() {
8976
8980
  return this._usage;
8977
8981
  }
@@ -8999,6 +9003,7 @@ var AnthropicStreamedMessage = class {
8999
9003
  }
9000
9004
  async *_convertNonStreamResponse(response) {
9001
9005
  this._id = response.id;
9006
+ this._model = response.model ?? null;
9002
9007
  this._extractUsage(response.usage);
9003
9008
  this._captureStopReason(response.stop_reason);
9004
9009
  for (const block of response.content) switch (block.type) {
@@ -9047,6 +9052,7 @@ var AnthropicStreamedMessage = class {
9047
9052
  if (eventType === "message_start") {
9048
9053
  const startEvt = evt;
9049
9054
  this._id = startEvt.message.id;
9055
+ this._model = startEvt.message.model ?? null;
9050
9056
  this._extractUsage(startEvt.message.usage);
9051
9057
  } else if (eventType === "content_block_start") {
9052
9058
  const blockEvt = evt;
@@ -45127,17 +45133,25 @@ function convertMessage$1(message, reasoningKey, toolMessageConversion) {
45127
45133
  }
45128
45134
  var OpenAILegacyStreamedMessage = class {
45129
45135
  _id = null;
45136
+ _model = null;
45130
45137
  _usage = null;
45131
45138
  _finishReason = null;
45132
45139
  _rawFinishReason = null;
45133
45140
  _iter;
45134
45141
  constructor(response, isStream, reasoningKey) {
45135
45142
  if (isStream) this._iter = this._convertStreamResponse(response, reasoningKey);
45136
- else this._iter = this._convertNonStreamResponse(response, reasoningKey);
45143
+ else {
45144
+ const reported = response.model;
45145
+ this._model = typeof reported === "string" && reported.length > 0 ? reported : null;
45146
+ this._iter = this._convertNonStreamResponse(response, reasoningKey);
45147
+ }
45137
45148
  }
45138
45149
  get id() {
45139
45150
  return this._id;
45140
45151
  }
45152
+ get model() {
45153
+ return this._model;
45154
+ }
45141
45155
  get usage() {
45142
45156
  return this._usage;
45143
45157
  }
@@ -45185,6 +45199,7 @@ var OpenAILegacyStreamedMessage = class {
45185
45199
  try {
45186
45200
  for await (const chunk of response) {
45187
45201
  if (chunk.id) this._id = chunk.id;
45202
+ if (this._model === null && typeof chunk.model === "string" && chunk.model.length > 0) this._model = chunk.model;
45188
45203
  if (chunk.usage) this._usage = extractUsage(chunk.usage) ?? null;
45189
45204
  if (!chunk.choices || chunk.choices.length === 0) continue;
45190
45205
  const choice = chunk.choices[0];
@@ -45632,6 +45647,7 @@ function convertTool(tool) {
45632
45647
  }
45633
45648
  var OpenAIResponsesStreamedMessage = class {
45634
45649
  _id = null;
45650
+ _model = null;
45635
45651
  _usage = null;
45636
45652
  _finishReason = null;
45637
45653
  _rawFinishReason = null;
@@ -45643,6 +45659,9 @@ var OpenAIResponsesStreamedMessage = class {
45643
45659
  get id() {
45644
45660
  return this._id;
45645
45661
  }
45662
+ get model() {
45663
+ return this._model;
45664
+ }
45646
45665
  get usage() {
45647
45666
  return this._usage;
45648
45667
  }
@@ -45676,6 +45695,7 @@ var OpenAIResponsesStreamedMessage = class {
45676
45695
  }
45677
45696
  async *_convertNonStreamResponse(response) {
45678
45697
  this._id = readStringField(response, "id") ?? null;
45698
+ this._model = readNullableStringField(response, "model") ?? null;
45679
45699
  const usage = readObjectField(response, "usage");
45680
45700
  if (usage !== void 0) this._extractUsage(usage);
45681
45701
  this._captureFinishReasonFromResponse(response);
@@ -45749,8 +45769,11 @@ var OpenAIResponsesStreamedMessage = class {
45749
45769
  break;
45750
45770
  case "response.created":
45751
45771
  case "response.in_progress": {
45752
- const respId = readStringField(requireObjectField(chunk, "response", type), "id");
45772
+ const responseObject = requireObjectField(chunk, "response", type);
45773
+ const respId = readStringField(responseObject, "id");
45753
45774
  if (respId !== void 0) this._id = respId;
45775
+ const respModel = readNullableStringField(responseObject, "model");
45776
+ if (respModel !== void 0) this._model = respModel;
45754
45777
  break;
45755
45778
  }
45756
45779
  case "response.output_item.added": {
@@ -46369,6 +46392,7 @@ async function generate(provider, systemPrompt, tools, history, callbacks, optio
46369
46392
  }
46370
46393
  return {
46371
46394
  id: stream.id,
46395
+ model: stream.model,
46372
46396
  message,
46373
46397
  usage: stream.usage,
46374
46398
  finishReason: stream.finishReason,
@@ -91349,6 +91373,7 @@ async function executeLoopStep(deps) {
91349
91373
  finishReason: effectiveStopReason,
91350
91374
  llmFirstTokenLatencyMs: response.streamTiming?.firstTokenLatencyMs,
91351
91375
  llmStreamDurationMs: response.streamTiming?.streamDurationMs,
91376
+ reportedModel: response.model,
91352
91377
  ...stepEndProviderDiagnostics(response, effectiveStopReason)
91353
91378
  });
91354
91379
  let stopTurnAfterStep = stopTurnAfterUsage;
@@ -97637,6 +97662,7 @@ var LtodLLM = class {
97637
97662
  providerFinishReason: result.finishReason ?? void 0,
97638
97663
  rawFinishReason: result.rawFinishReason ?? void 0,
97639
97664
  usage: result.usage ?? emptyUsage(),
97665
+ model: result.model ?? void 0,
97640
97666
  streamTiming: firstChunkAt === void 0 ? void 0 : buildStreamTiming(chatStartedAt, requestStartedAt, firstChunkAt, streamEndedAt)
97641
97667
  };
97642
97668
  }
@@ -119493,8 +119519,8 @@ var LocalJian = class LocalJian {
119493
119519
  * callers can therefore operate on independent working directories
119494
119520
  * without polluting one another.
119495
119521
  */
119496
- static async create(cwd, rootDir) {
119497
- return new LocalJian(await detectEnvironmentFromNode(), cwd, rootDir);
119522
+ static async create(cwd, rootDir, env) {
119523
+ return new LocalJian(env ?? await detectEnvironmentFromNode(), cwd, rootDir);
119498
119524
  }
119499
119525
  withCwd(cwd) {
119500
119526
  return new LocalJian(this.osEnv, cwd, this._rootDir);
@@ -119782,6 +119808,40 @@ function waitForSpawn(child) {
119782
119808
  new AsyncLocalStorage();
119783
119809
  //#endregion
119784
119810
  //#region ../../packages/agent-core/src/rpc/core-impl.ts
119811
+ const ENV_CACHE_TTL_MS = 10080 * 60 * 1e3;
119812
+ /**
119813
+ * Reads a previously detected host environment from the scream home dir.
119814
+ * Windows environment detection walks PATH and stats dozens of candidates
119815
+ * (~60-110 filesystem probes), so every fresh process paid that cost at
119816
+ * startup. Returns `undefined` when the cache is missing, expired, or the
119817
+ * entry's shell no longer exists (verified with a single stat).
119818
+ */
119819
+ async function readEnvironmentCache(homeDir) {
119820
+ try {
119821
+ const raw = await readFile(join$1(homeDir, "environment-cache.json"), "utf8");
119822
+ const entry = JSON.parse(raw);
119823
+ if (typeof entry?.cachedAt !== "number" || Date.now() - entry.cachedAt >= ENV_CACHE_TTL_MS) return;
119824
+ if (entry.osVersion !== release()) return;
119825
+ if (typeof entry.shellPath !== "string" || entry.shellPath.length === 0) return;
119826
+ const explicitShell = process.env["SCREAM_SHELL_PATH"]?.trim();
119827
+ if (explicitShell !== void 0 && explicitShell.length > 0) {
119828
+ if (!(process.platform === "win32" ? explicitShell.toLowerCase() === entry.shellPath.toLowerCase() : explicitShell === entry.shellPath)) return;
119829
+ }
119830
+ if (!(await stat(entry.shellPath)).isFile()) return;
119831
+ const { cachedAt: _cachedAt, ...env } = entry;
119832
+ return env;
119833
+ } catch {
119834
+ return;
119835
+ }
119836
+ }
119837
+ /** Persists a detected host environment so the next process can skip detection. */
119838
+ async function writeEnvironmentCache(homeDir, env) {
119839
+ const entry = {
119840
+ ...env,
119841
+ cachedAt: Date.now()
119842
+ };
119843
+ await writeFile(join$1(homeDir, "environment-cache.json"), JSON.stringify(entry), "utf8");
119844
+ }
119785
119845
  var ScreamCore = class {
119786
119846
  rpcClient;
119787
119847
  sdk;
@@ -119808,7 +119868,7 @@ var ScreamCore = class {
119808
119868
  homeDir: this.homeDir,
119809
119869
  configPath: options.configPath
119810
119870
  });
119811
- this.jian = LocalJian.create().catch((error) => {
119871
+ this.jian = this.resolveLocalJian().catch((error) => {
119812
119872
  if (error instanceof JianShellNotFoundError) throw new ScreamError(ErrorCodes.SHELL_GIT_BASH_NOT_FOUND, error.message);
119813
119873
  throw error;
119814
119874
  });
@@ -119830,10 +119890,25 @@ var ScreamCore = class {
119830
119890
  setSubagentModelBindings(getter) {
119831
119891
  this.subagentModelBindings = getter;
119832
119892
  }
119833
- /** Resolve the shell environment so missing Git Bash is surfaced early. */
119893
+ /**
119894
+ * Resolve the shell environment so missing Git Bash is surfaced early.
119895
+ */
119834
119896
  async preflight() {
119835
119897
  await this.jian;
119836
119898
  }
119899
+ /**
119900
+ * Builds the LocalJian, preferring a cached host environment so Windows
119901
+ * startups skip the expensive PATH/filesystem detection. On a cache miss
119902
+ * the full detection runs once and the result is persisted for the next
119903
+ * process.
119904
+ */
119905
+ async resolveLocalJian() {
119906
+ const cached = await readEnvironmentCache(this.homeDir);
119907
+ if (cached !== void 0) return LocalJian.create(void 0, void 0, cached);
119908
+ const jian = await LocalJian.create();
119909
+ await writeEnvironmentCache(this.homeDir, jian.osEnv).catch(() => {});
119910
+ return jian;
119911
+ }
119837
119912
  async createSession(input) {
119838
119913
  const options = input;
119839
119914
  const workDir = requiredWorkDir("createSession", options.workDir);
@@ -127681,6 +127756,46 @@ var WelcomeComponent = class {
127681
127756
  }
127682
127757
  };
127683
127758
  //#endregion
127759
+ //#region src/tui/components/messages/wrapped-line.ts
127760
+ var WrappedLine = class {
127761
+ firstPrefix;
127762
+ continuationPrefix;
127763
+ text;
127764
+ options;
127765
+ cachedText;
127766
+ cachedWidth;
127767
+ cachedLines;
127768
+ constructor(firstPrefix, continuationPrefix, text, options = {}) {
127769
+ this.firstPrefix = firstPrefix;
127770
+ this.continuationPrefix = continuationPrefix;
127771
+ this.text = text;
127772
+ this.options = options;
127773
+ }
127774
+ render(width) {
127775
+ if (this.cachedLines !== void 0 && this.cachedText === this.text && this.cachedWidth === width) return this.cachedLines;
127776
+ const prefixWidth = Math.max(visibleWidth(this.firstPrefix), visibleWidth(this.continuationPrefix));
127777
+ const contentWidth = Math.max(1, width - prefixWidth);
127778
+ let lines;
127779
+ if (this.options.truncate === true) if (!this.text || this.text.trim() === "") lines = [];
127780
+ else {
127781
+ const singleLine = this.text.replaceAll(/\r\n|\r|\n/g, " ").replaceAll(/\t/g, " ");
127782
+ const line = this.firstPrefix + truncateToWidth(singleLine, contentWidth);
127783
+ const pad = Math.max(0, width - visibleWidth(line));
127784
+ lines = [line + " ".repeat(pad)];
127785
+ }
127786
+ else lines = new Text(this.text, 0, 0).render(contentWidth).map((line, index) => index === 0 ? `${this.firstPrefix}${line}` : `${this.continuationPrefix}${line}`);
127787
+ this.cachedText = this.text;
127788
+ this.cachedWidth = width;
127789
+ this.cachedLines = lines;
127790
+ return lines;
127791
+ }
127792
+ invalidate() {
127793
+ this.cachedText = void 0;
127794
+ this.cachedWidth = void 0;
127795
+ this.cachedLines = void 0;
127796
+ }
127797
+ };
127798
+ //#endregion
127684
127799
  //#region src/tui/components/messages/agent-group.ts
127685
127800
  const THROTTLE_MS$1 = 200;
127686
127801
  var AgentGroupComponent = class extends Container {
@@ -127818,18 +127933,20 @@ var AgentGroupComponent = class extends Container {
127818
127933
  const agentType = snap.agentName ?? "agent";
127819
127934
  const desc = snap.toolCallDescription || t("agentgroup.no_desc");
127820
127935
  const tail = formatLineTail(snap, colors);
127821
- const line1 = ` ${branch1} ${chalk.hex(colors.primary)(agentType)} ${dim(`· ${desc}`)}${formatStats(snap)}${tail}`;
127822
- this.bodyContainer.addChild(new Text(line1, 0, 0));
127823
- const branch2 = isLast ? " " : "│ ";
127936
+ const line1Content = `${chalk.hex(colors.primary)(agentType)} ${dim(`· ${desc}`)}${formatStats(snap)}${tail}`;
127937
+ const branchPrefix = ` ${branch1} `;
127938
+ const branchContinuation = isLast ? " " : " │ ";
127939
+ this.bodyContainer.addChild(new WrappedLine(branchPrefix, branchContinuation, line1Content, { truncate: true }));
127940
+ const childPrefix = ` ${isLast ? " " : "│ "} `;
127824
127941
  if (snap.phase === "failed") {
127825
- const errLine = (snap.errorText ?? t("agentgroup.failed")).split("\n").at(0) ?? t("agentgroup.failed");
127942
+ const errLine = (snap.errorText ?? t("agentgroup.failed")).split(/\r\n|\r|\n/).at(0) ?? t("agentgroup.failed");
127826
127943
  const errStr = chalk.hex(colors.error)(`${t("agentgroup.error")}${errLine}`);
127827
- this.bodyContainer.addChild(new Text(` ${branch2} ${errStr}`, 0, 0));
127944
+ this.bodyContainer.addChild(new WrappedLine(childPrefix, childPrefix, errStr));
127828
127945
  return;
127829
127946
  }
127830
127947
  if (snap.phase === "done" || snap.phase === "backgrounded") return;
127831
127948
  const activity = snap.latestActivity ?? t("agentgroup.initializing");
127832
- this.bodyContainer.addChild(new Text(` ${branch2} ${dim(activity)}`, 0, 0));
127949
+ this.bodyContainer.addChild(new WrappedLine(childPrefix, childPrefix, dim(activity), { truncate: true }));
127833
127950
  }
127834
127951
  /** Releases throttle timers so destroyed components cannot refresh later. */
127835
127952
  dispose() {
@@ -127842,7 +127959,7 @@ var AgentGroupComponent = class extends Container {
127842
127959
  };
127843
127960
  function formatStats(snap) {
127844
127961
  const dim = chalk.dim;
127845
- return dim(`${` · ${String(snap.toolCount)} tool${snap.toolCount === 1 ? "" : "s"}`}${snap.tokens > 0 ? ` · ${formatTokens$1(snap.tokens)}` : ""}`);
127962
+ return dim(`${snap.toolCount > 0 ? ` · ${String(snap.toolCount)} tool${snap.toolCount === 1 ? "" : "s"}` : ""}${snap.tokens > 0 ? ` · ${formatTokens$1(snap.tokens)}` : ""}`);
127846
127963
  }
127847
127964
  function formatLineTail(snap, colors) {
127848
127965
  if (snap.phase === "done") return chalk.dim(" · ") + chalk.hex(colors.success)(t("agentgroup.check_done"));
@@ -128236,7 +128353,7 @@ var ReadGroupComponent = class extends Container {
128236
128353
  const visibleSnapshots = snapshots.filter((snap) => snap.filePath !== void 0 && snap.filePath.length > 0);
128237
128354
  visibleSnapshots.forEach((snap, idx) => {
128238
128355
  const isLast = idx === visibleSnapshots.length - 1;
128239
- this.bodyContainer.addChild(new Text(this.buildBodyLine(snap, isLast), 0, 0));
128356
+ this.addBodyBranch(snap.filePath ?? "", isLast, this.buildBodyTail(snap));
128240
128357
  });
128241
128358
  this.lastFlushPhases.clear();
128242
128359
  this.entries.forEach((entry, i) => {
@@ -128256,7 +128373,7 @@ var ReadGroupComponent = class extends Container {
128256
128373
  this.bodyContainer.clear();
128257
128374
  results.forEach((r, idx) => {
128258
128375
  const isLast = idx === results.length - 1;
128259
- this.bodyContainer.addChild(new Text(this.buildDirectBodyLine(r, isLast), 0, 0));
128376
+ this.addBodyBranch(r.filePath, isLast, this.buildDirectBodyTail(r));
128260
128377
  });
128261
128378
  this.invalidate();
128262
128379
  this.ui?.requestRender();
@@ -128268,30 +128385,28 @@ var ReadGroupComponent = class extends Container {
128268
128385
  if (failed === total) return `${chalk.hex(colors.error)("✗ ")}${chalk.hex(colors.error).bold(t("readgroup.read", { count: total }))}${chalk.hex(colors.error)(t("readgroup.failed_suffix"))}`;
128269
128386
  return `${chalk.hex(colors.success)(STATUS_BULLET)}${chalk.hex(colors.primary).bold(t("readgroup.read", { count: total }))}${dim(t("readgroup.lines_suffix", { count: totalLines }))}${failed > 0 ? chalk.hex(colors.error)(t("readgroup.failed_count", { count: failed })) : ""}`;
128270
128387
  }
128271
- buildBodyLine(snap, isLast) {
128272
- const colors = this.colors;
128388
+ /**
128389
+ * Renders one tree-branch body line with a hanging-indent continuation,
128390
+ * so a path longer than the viewport keeps its branch connector instead
128391
+ * of breaking the tree.
128392
+ */
128393
+ addBodyBranch(path, isLast, tail) {
128394
+ const prefix = ` ${isLast ? "└─" : "├─"} `;
128395
+ const continuation = isLast ? " " : " │ ";
128396
+ this.bodyContainer.addChild(new WrappedLine(prefix, continuation, `${chalk.hex(this.colors.text)(path)}${tail}`));
128397
+ }
128398
+ buildBodyTail(snap) {
128273
128399
  const dim = chalk.dim;
128274
- const branch = isLast ? "└─" : "├─";
128275
- const path = snap.filePath ?? "";
128276
- const pathPart = chalk.hex(colors.text)(path);
128277
- let tail;
128278
- if (snap.phase === "pending") tail = dim(t("readgroup.reading_suffix"));
128279
- else if (snap.phase === "failed") tail = chalk.hex(colors.error)(t("readgroup.failed_suffix"));
128280
- else tail = dim(t("readgroup.lines_suffix", { count: snap.lines }));
128281
- return ` ${branch} ${pathPart}${tail}`;
128282
- }
128283
- buildDirectBodyLine(result, isLast) {
128284
- const colors = this.colors;
128400
+ if (snap.phase === "pending") return dim(t("readgroup.reading_suffix"));
128401
+ if (snap.phase === "failed") return chalk.hex(this.colors.error)(t("readgroup.failed_suffix"));
128402
+ return dim(t("readgroup.lines_suffix", { count: snap.lines }));
128403
+ }
128404
+ buildDirectBodyTail(result) {
128285
128405
  const dim = chalk.dim;
128286
- const branch = isLast ? "└─" : "├─";
128287
- const pathPart = chalk.hex(colors.text)(result.filePath);
128288
- let tail;
128289
- if (result.failed) tail = chalk.hex(colors.error)(t("readgroup.failed_suffix"));
128290
- else {
128291
- tail = dim(t("readgroup.lines_suffix", { count: result.lines }));
128292
- if (result.hasConflicts) tail = `${tail}${chalk.hex(colors.warning)(` ⚠ ${t("readgroup.conflict_suffix")}`)}`;
128293
- }
128294
- return ` ${branch} ${pathPart}${tail}`;
128406
+ if (result.failed) return chalk.hex(this.colors.error)(t("readgroup.failed_suffix"));
128407
+ let tail = dim(t("readgroup.lines_suffix", { count: result.lines }));
128408
+ if (result.hasConflicts) tail = `${tail}${chalk.hex(this.colors.warning)(` ⚠ ${t("readgroup.conflict_suffix")}`)}`;
128409
+ return tail;
128295
128410
  }
128296
128411
  /** Releases throttle timers so destroyed components cannot refresh later. */
128297
128412
  dispose() {
@@ -130053,22 +130168,6 @@ function tailNonEmptyLines(text, maxLines) {
130053
130168
  if (text.length === 0) return [];
130054
130169
  return text.split("\n").map((line) => line.trimEnd()).filter((line) => line.trim().length > 0).slice(-maxLines);
130055
130170
  }
130056
- var PrefixedWrappedLine = class {
130057
- firstPrefix;
130058
- continuationPrefix;
130059
- text;
130060
- constructor(firstPrefix, continuationPrefix, text) {
130061
- this.firstPrefix = firstPrefix;
130062
- this.continuationPrefix = continuationPrefix;
130063
- this.text = text;
130064
- }
130065
- invalidate() {}
130066
- render(width) {
130067
- const prefixWidth = Math.max(visibleWidth(this.firstPrefix), visibleWidth(this.continuationPrefix));
130068
- const contentWidth = Math.max(1, width - prefixWidth);
130069
- return new Text(this.text, 0, 0).render(contentWidth).map((line, index) => index === 0 ? `${this.firstPrefix}${line}` : `${this.continuationPrefix}${line}`);
130070
- }
130071
- };
130072
130171
  var ToolCallComponent = class ToolCallComponent extends CachedContainer {
130073
130172
  workspaceDir;
130074
130173
  expanded = false;
@@ -130426,7 +130525,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
130426
130525
  }
130427
130526
  syncSubagentElapsedTimer() {
130428
130527
  const phase = this.getDerivedSubagentPhase();
130429
- if (!(this.isSingleSubagentView() && this.subagentStartedAtMs !== void 0 && (phase === "spawning" || phase === "running"))) {
130528
+ if (!(this.isSingleSubagentView() && this.onSnapshotChange === void 0 && this.subagentStartedAtMs !== void 0 && (phase === "spawning" || phase === "running"))) {
130430
130529
  this.stopSubagentElapsedTimer();
130431
130530
  return;
130432
130531
  }
@@ -130783,7 +130882,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
130783
130882
  }
130784
130883
  if (this.subagentText.length > 0) {
130785
130884
  const tailLines = this.subagentText.split("\n").slice(-3);
130786
- for (const line of tailLines) this.addChild(new Text(` ${dim(line)}`, 0, 0));
130885
+ for (const line of tailLines) this.addChild(new WrappedLine(" ", " ", dim(line)));
130787
130886
  }
130788
130887
  if (this.subagentPhase === "done" && this.subagentResultSummary !== void 0) {
130789
130888
  const summaryLines = this.subagentResultSummary.split("\n").slice(0, 2);
@@ -130894,13 +130993,13 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
130894
130993
  }
130895
130994
  if (this.getDerivedSubagentPhase() === "failed" && this.subagentError !== void 0) {
130896
130995
  const errorLine = tailNonEmptyLines(this.subagentError, 1).at(-1);
130897
- if (errorLine !== void 0) this.addChild(new PrefixedWrappedLine(` ${chalk.hex(this.colors.error)("└")} `, " ", chalk.hex(this.colors.error)(errorLine)));
130996
+ if (errorLine !== void 0) this.addChild(new WrappedLine(` ${chalk.hex(this.colors.error)("└")} `, " ", chalk.hex(this.colors.error)(errorLine)));
130898
130997
  return;
130899
130998
  }
130900
130999
  const outputLine = tailNonEmptyLines(this.subagentText, 1).at(-1);
130901
131000
  const thinkingLine = tailNonEmptyLines(this.subagentThinkingText, 1).at(-1);
130902
- if (this.getDerivedSubagentPhase() !== "done" && thinkingLine !== void 0) this.addChild(new PrefixedWrappedLine(` ${chalk.dim("◌")} `, " ", chalk.dim(thinkingLine)));
130903
- if (outputLine !== void 0) this.addChild(new PrefixedWrappedLine(` ${chalk.hex(this.colors.text)("└")} `, " ", chalk.hex(this.colors.text)(outputLine)));
131001
+ if (this.getDerivedSubagentPhase() !== "done" && thinkingLine !== void 0) this.addChild(new WrappedLine(` ${chalk.dim("◌")} `, " ", chalk.dim(thinkingLine), { truncate: true }));
131002
+ if (outputLine !== void 0) this.addChild(new WrappedLine(` ${chalk.hex(this.colors.text)("└")} `, " ", chalk.hex(this.colors.text)(outputLine), { truncate: true }));
130904
131003
  }
130905
131004
  getRecentSubToolActivities() {
130906
131005
  return [...this.subToolActivities.values()].toSorted((a, b) => a.orderSeq - b.orderSeq).slice(-4);
package/dist/main.mjs CHANGED
@@ -6,7 +6,7 @@ const __dirname = __cjsShimDirname(__filename);
6
6
  import "./suppress-sqlite-warning-C2VB0doZ.mjs";
7
7
  //#region src/main.ts
8
8
  try {
9
- (await import("./app-8FWNOsdU.mjs")).main();
9
+ (await import("./app-DMvVE2Uq.mjs")).main();
10
10
  } catch (error) {
11
11
  process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
12
12
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scream-code",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
4
4
  "description": "A terminal-native AI agent for builders",
5
5
  "license": "MIT",
6
6
  "author": "ScreamCli",