scream-code 0.17.6 → 0.17.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
@@ -103,7 +103,7 @@ Type `/` in the input to browse. All 55 commands:
103
103
  | `/knowledge` (`/know`) `[query]` | Manage local knowledge base |
104
104
  | **Models & configuration** | |
105
105
  | `/model [alias]` | Switch LLM model |
106
- | `/config` | Browse and configure models |
106
+ | `/config` (`/login`) | Browse and configure models |
107
107
  | `/config image` | Configure image generation (provider, URL, key, model) |
108
108
  | `/logout` (`/disconnect`) | Remove configured models |
109
109
  | `/language` (`/lang`) | Switch interface language |
@@ -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 { k as MemoryMemoStore } from "./src-BhZujafw.mjs";
8
- import { $n as encodeWorkDirKey, $t as lerpGradient, A as highlightLines, An as embeddingFailureDetail, At as isTurnElapsedEnabled, B as ActivityGroupComponent, Bn as detectShellEnvironment, Bt as ENABLE_TERMINAL_THEME_REPORTING, Cn as getLlmNotSetMessage, Ct as clearInfoPanelState, D as ToolCallComponent, Dn as sortSlashCommands, Dt as createEditorTheme, E as UserMessageComponent, En as BUILTIN_SLASH_COMMANDS, Et as resolveThemeSync, F as StatusMessageComponent, Fn as PULSE_WAVE_FRAMES, Ft as detectTerminalTheme, G as AgentGroupComponent, Gn as CLI_COMMAND_NAME, Gt as QUERY_TERMINAL_THEME, H as estimateTokens, Hn as getInputHistoryFile, Ht as OSC11_RESPONSE, I as replaceTabs, In as TuiConfigParseError, It as parseOsc11BackgroundTheme, J as getBreathingFrame, Jn as PRODUCT_NAME, Jt as TERMINAL_THEME_DARK, K as WelcomeComponent, Kn as CLI_UI_MODE, Kt as TERMINAL_FOCUS_IN, L as sanitizeShellOutput, Ln as TuiLikePreferencesSchema, Lt as DISABLE_TERMINAL_FOCUS_REPORTING, M as CachedContainer, Mn as hasEmbeddingModelCache, Mt as createThemeStyles, N as ThinkingComponent, Nn as startManualEmbeddingDownload, Nt as contrastTextHex, O as renderDiffLines, On as isExperimentalFlagEnabled, Ot as createMarkdownTheme, P as NoticeMessageComponent, Pn as PIXEL_PULSE_FRAMES, Pt as getColorPalette, Q as refineGoal, Qn as ScreamHarness, Qt as FooterComponent, R as SkillActivationComponent, Rn as loadTuiConfig, Rt as DISABLE_TERMINAL_THEME_REPORTING, S as readJsonlFile, Sn as getCtrlDHint, St as supportsBalance, Tn as buildSkillSlashCommands, U as getSharedSpeedTracker, Un as getLogDir, Ut as OSC11_RESPONSE_PREFIX, V as charsForTokenBudget, Vn as getDataDir, Vt as OSC11_QUERY, W as BackgroundAgentStatusComponent, Wn as detectInstallSource, Wt as OSC11_RESPONSE_PREFIX_NO_ESC, X as CompactionComponent, Xn as fetchCatalog, Xt as isBusy, Y as resetBreathingClock, Yn as DEFAULT_CATALOG_URL, Yt as TERMINAL_THEME_LIGHT, Z as clearGoalState, Zn as saveCatalogCache, Zt as isStreaming, _n as EXIT_CONFIRM_WINDOW_MS, a as syncDiagramCapabilityPrompt, an as printableChar, ar as isRealUserPrompt, at as toTerminalHyperlink, b as readUpdateCache, bn as TIP_ROTATION_INTERVAL_MS, c as disposeChildren, cn as appendStreamingArgsPreview, cr as log, d as isPlanExpandable, dn as isTodoItemShape, dr as isOrphanedToolCallError, en as SubagentSlots, er as normalizeWorkDir, f as MoonLoader, fn as parseStreamingArgs, fr as ErrorCodes, ft as handleFusionPlanCommand, gn as EMPTY_SESSION_HINT_URL, hn as truncateErrorMessage, i as buildRoleAdditionalText, it as isInternalMessage, j as langFromPath, jn as getKnowledgeStore, jt as toggleEmptySessionHint, k as renderDiffLinesClustered, kn as setExperimentalFlags, kt as isEmptySessionHintDismissed, l as hasDispose, ln as argsRecord, lr as resolveGlobalLogPath, mn as stringValue, mt as handlePlanCommand, n as clearEvalPanelState, nr as readSessionIndex, on as STATUS_BULLET, or as resolveScreamHome, ot as changeThinkingLevel, p as formatMemoryMemoForInjection, pn as serializeToolResultOutput, pr as SCREAM_ERROR_INFO, q as BREATHE_CYCLE_MS, qn as CLI_USER_AGENT_PRODUCT, qt as TERMINAL_FOCUS_OUT, r as openUrl, rr as removeSessionIndexEntry, sn as appendSessionHeaderHint, sr as flushDiagnosticLogs, st as getModelCycleLevel, t as dispatchInput, tr as appendSessionIndexEntry, u as isExpandable, un as formatErrorMessage, ur as isScreamError, v as selectUpdateTarget, vn as MAIN_AGENT_ID, w as getDaemonInstructions, wn as getNoActiveSessionMessage, x as appendJsonlLine, xn as getCtrlCHint, xt as refreshProviderBalance, y as refreshUpdateCache, yn as SESSION_TIPS, z as AssistantMessageComponent, zn as saveTuiConfig, zt as ENABLE_TERMINAL_FOCUS_REPORTING } from "./dispatch-DFFuylzQ.mjs";
8
+ import { $n as encodeWorkDirKey, $t as lerpGradient, A as highlightLines, An as embeddingFailureDetail, At as isTurnElapsedEnabled, B as ActivityGroupComponent, Bn as detectShellEnvironment, Bt as ENABLE_TERMINAL_THEME_REPORTING, Cn as getLlmNotSetMessage, Ct as clearInfoPanelState, D as ToolCallComponent, Dn as sortSlashCommands, Dt as createEditorTheme, E as UserMessageComponent, En as BUILTIN_SLASH_COMMANDS, Et as resolveThemeSync, F as StatusMessageComponent, Fn as PULSE_WAVE_FRAMES, Ft as detectTerminalTheme, G as AgentGroupComponent, Gn as CLI_COMMAND_NAME, Gt as QUERY_TERMINAL_THEME, H as estimateTokens, Hn as getInputHistoryFile, Ht as OSC11_RESPONSE, I as replaceTabs, In as TuiConfigParseError, It as parseOsc11BackgroundTheme, J as getBreathingFrame, Jn as PRODUCT_NAME, Jt as TERMINAL_THEME_DARK, K as WelcomeComponent, Kn as CLI_UI_MODE, Kt as TERMINAL_FOCUS_IN, L as sanitizeShellOutput, Ln as TuiLikePreferencesSchema, Lt as DISABLE_TERMINAL_FOCUS_REPORTING, M as CachedContainer, Mn as hasEmbeddingModelCache, Mt as createThemeStyles, N as ThinkingComponent, Nn as startManualEmbeddingDownload, Nt as contrastTextHex, O as renderDiffLines, On as isExperimentalFlagEnabled, Ot as createMarkdownTheme, P as NoticeMessageComponent, Pn as PIXEL_PULSE_FRAMES, Pt as getColorPalette, Q as refineGoal, Qn as ScreamHarness, Qt as FooterComponent, R as SkillActivationComponent, Rn as loadTuiConfig, Rt as DISABLE_TERMINAL_THEME_REPORTING, S as readJsonlFile, Sn as getCtrlDHint, St as supportsBalance, Tn as buildSkillSlashCommands, U as getSharedSpeedTracker, Un as getLogDir, Ut as OSC11_RESPONSE_PREFIX, V as charsForTokenBudget, Vn as getDataDir, Vt as OSC11_QUERY, W as BackgroundAgentStatusComponent, Wn as detectInstallSource, Wt as OSC11_RESPONSE_PREFIX_NO_ESC, X as CompactionComponent, Xn as fetchCatalog, Xt as isBusy, Y as resetBreathingClock, Yn as DEFAULT_CATALOG_URL, Yt as TERMINAL_THEME_LIGHT, Z as clearGoalState, Zn as saveCatalogCache, Zt as isStreaming, _n as EXIT_CONFIRM_WINDOW_MS, a as syncDiagramCapabilityPrompt, an as printableChar, ar as isRealUserPrompt, at as toTerminalHyperlink, b as readUpdateCache, bn as TIP_ROTATION_INTERVAL_MS, c as disposeChildren, cn as appendStreamingArgsPreview, cr as log, d as isPlanExpandable, dn as isTodoItemShape, dr as isOrphanedToolCallError, en as SubagentSlots, er as normalizeWorkDir, f as MoonLoader, fn as parseStreamingArgs, fr as ErrorCodes, ft as handleFusionPlanCommand, gn as EMPTY_SESSION_HINT_URL, hn as truncateErrorMessage, i as buildRoleAdditionalText, it as isInternalMessage, j as langFromPath, jn as getKnowledgeStore, jt as toggleEmptySessionHint, k as renderDiffLinesClustered, kn as setExperimentalFlags, kt as isEmptySessionHintDismissed, l as hasDispose, ln as argsRecord, lr as resolveGlobalLogPath, mn as stringValue, mt as handlePlanCommand, n as clearEvalPanelState, nr as readSessionIndex, on as STATUS_BULLET, or as resolveScreamHome, ot as changeThinkingLevel, p as formatMemoryMemoForInjection, pn as serializeToolResultOutput, pr as SCREAM_ERROR_INFO, q as BREATHE_CYCLE_MS, qn as CLI_USER_AGENT_PRODUCT, qt as TERMINAL_FOCUS_OUT, r as openUrl, rr as removeSessionIndexEntry, sn as appendSessionHeaderHint, sr as flushDiagnosticLogs, st as getModelCycleLevel, t as dispatchInput, tr as appendSessionIndexEntry, u as isExpandable, un as formatErrorMessage, ur as isScreamError, v as selectUpdateTarget, vn as MAIN_AGENT_ID, w as getDaemonInstructions, wn as getNoActiveSessionMessage, x as appendJsonlLine, xn as getCtrlCHint, xt as refreshProviderBalance, y as refreshUpdateCache, yn as SESSION_TIPS, z as AssistantMessageComponent, zn as saveTuiConfig, zt as ENABLE_TERMINAL_FOCUS_REPORTING } from "./dispatch-B8IVXCrX.mjs";
9
9
  import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-CD0sakGq.mjs";
10
10
  import { createRequire } from "node:module";
11
11
  import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
@@ -33,7 +33,7 @@ function optionalBuildString(value) {
33
33
  return typeof value === "string" && value.length > 0 ? value : void 0;
34
34
  }
35
35
  const SCREAM_BUILD_INFO = {
36
- version: optionalBuildString("0.17.6"),
36
+ version: optionalBuildString("0.17.8"),
37
37
  channel: optionalBuildString(""),
38
38
  commit: optionalBuildString(""),
39
39
  buildTarget: optionalBuildString("darwin-arm64")
@@ -4874,9 +4874,12 @@ var StreamingUIController = class StreamingUIController {
4874
4874
  }
4875
4875
  /**
4876
4876
  * Advance the smooth-render cursor by this frame's character budget.
4877
- * Budget clamps to the measured arrival rate (fast models keep up, slow
4878
- * models never fall behind) with a floor so the stream never freezes and a
4879
- * ceiling so one oversized burst is spread across frames.
4877
+ * The base budget clamps to the measured arrival rate (slow models never
4878
+ * fall behind) with a floor so the stream never freezes and a ceiling so one
4879
+ * oversized burst is spread across frames. Once the backlog passes
4880
+ * SMOOTH_CATCHUP_THRESHOLD, a catch-up budget (backlog / DIVISOR, capped at
4881
+ * MAX_PER_FRAME) raises it so a fast stream converges to a bounded lag
4882
+ * instead of accumulating until finalize.
4880
4883
  */
4881
4884
  advanceAssistantShown() {
4882
4885
  const draft = this._assistantDraft;
@@ -4884,7 +4887,9 @@ var StreamingUIController = class StreamingUIController {
4884
4887
  const measured = getSharedSpeedTracker().getSpeed();
4885
4888
  const tokPerSec = measured > 0 ? measured : 50;
4886
4889
  const requested = charsForTokenBudget(draft.slice(this._shownAssistantLength), tokPerSec * (50 / 1e3));
4887
- const budget = Math.min(25, Math.max(1, requested));
4890
+ let budget = Math.min(25, Math.max(1, requested));
4891
+ const backlog = draft.length - this._shownAssistantLength;
4892
+ if (backlog > 250) budget = Math.max(budget, Math.min(Math.ceil(backlog / 8), 300));
4888
4893
  this._shownAssistantLength = Math.min(draft.length, this._shownAssistantLength + budget);
4889
4894
  return this._shownAssistantLength;
4890
4895
  }
@@ -11159,7 +11164,7 @@ var SessionManager$1 = class {
11159
11164
  this.host = host;
11160
11165
  }
11161
11166
  async init(options) {
11162
- const { startup, workDir } = options;
11167
+ const { startup, workDir, sessionsPrefetch } = options;
11163
11168
  let session;
11164
11169
  let shouldReplayHistory = false;
11165
11170
  const isResumeStartup = startup.sessionFlag !== void 0 || startup.continueLast;
@@ -11175,12 +11180,9 @@ var SessionManager$1 = class {
11175
11180
  throw new Error("picker");
11176
11181
  }
11177
11182
  if (startup.sessionFlag !== void 0) {
11178
- const target = (await this.host.harness.listSessions({
11179
- sessionId: startup.sessionFlag,
11180
- workDir
11181
- }))[0];
11183
+ const target = await this.findSessionById(startup.sessionFlag, workDir);
11182
11184
  if (target === void 0) throw new Error(t("session.not_found", { sessionId: startup.sessionFlag }));
11183
- if (target.workDir !== workDir) throw new Error(t("session.wrong_dir", {
11185
+ if (normalizeWorkDir(target.workDir) !== normalizeWorkDir(workDir)) throw new Error(t("session.wrong_dir", {
11184
11186
  sessionId: startup.sessionFlag,
11185
11187
  workDir: target.workDir
11186
11188
  }));
@@ -11203,7 +11205,7 @@ var SessionManager$1 = class {
11203
11205
  await this.syncRuntimeState(session);
11204
11206
  if (startup.wolfpack && !isResumeStartup) await session.setWolfpackMode(true);
11205
11207
  this.host.state.startupState = "ready";
11206
- await this.pruneEmptySessions(workDir, session.id);
11208
+ await this.pruneEmptySessions(workDir, session.id, sessionsPrefetch);
11207
11209
  this.host.sessionEventHandler.startSubscription();
11208
11210
  return {
11209
11211
  session,
@@ -11216,21 +11218,46 @@ var SessionManager$1 = class {
11216
11218
  * one-off empty session shells. The session about to be used is skipped, as
11217
11219
  * are archived sessions, any session that produced a prompt or a title, and
11218
11220
  * any session touched within the grace window (protects a fresh empty
11219
- * session being used from another terminal). Best-effort: cleanup failures
11220
- * never block startup.
11221
+ * session being used from another terminal). The prefetched listing, when
11222
+ * present, only enumerates candidates: the snapshot can lag the splash
11223
+ * duration, so every candidate is re-checked against a live id lookup and is
11224
+ * deleted only if it still looks prunable right now (a session that woke up
11225
+ * meanwhile — prompt, rename, new activity — stays). Best-effort: cleanup
11226
+ * failures never block startup.
11221
11227
  */
11222
- async pruneEmptySessions(workDir, currentSessionId) {
11228
+ async pruneEmptySessions(workDir, currentSessionId, prefetch) {
11223
11229
  try {
11224
11230
  const now = Date.now();
11225
- const summaries = await this.host.harness.listSessions({ workDir });
11226
- for (const summary of summaries) {
11231
+ const normalizedWorkDir = normalizeWorkDir(workDir);
11232
+ const candidates = prefetch === void 0 ? await this.host.harness.listSessions({ workDir }) : await prefetch;
11233
+ for (const summary of candidates) {
11227
11234
  if (summary.id === currentSessionId) continue;
11228
- if (isPrunableEmptySession(summary, now)) await this.host.harness.deleteSession(summary.id).catch(() => {});
11235
+ if (!isPrunableEmptySession(summary, now)) continue;
11236
+ const latest = (await this.host.harness.listSessions({
11237
+ sessionId: summary.id,
11238
+ workDir
11239
+ }))[0];
11240
+ if (latest === void 0) continue;
11241
+ if (normalizeWorkDir(latest.workDir) !== normalizedWorkDir) continue;
11242
+ if (!isPrunableEmptySession(latest, Date.now())) continue;
11243
+ await this.host.harness.deleteSession(summary.id).catch(() => {});
11229
11244
  }
11230
11245
  } catch (error) {
11231
11246
  this.host.showStatus(`Session cleanup skipped: ${String(error)}`);
11232
11247
  }
11233
11248
  }
11249
+ /**
11250
+ * Resolve the `--session <id>` target from a live listing (resume decisions
11251
+ * never read the prefetched snapshot). The id-filtered form is the only call
11252
+ * that can tell "no such session" apart from "session lives in another
11253
+ * workDir".
11254
+ */
11255
+ async findSessionById(sessionId, workDir) {
11256
+ return (await this.host.harness.listSessions({
11257
+ sessionId,
11258
+ workDir
11259
+ }))[0];
11260
+ }
11234
11261
  async setSession(session) {
11235
11262
  await this.unloadCurrentSession("switching session")?.close({ extractMemories: false });
11236
11263
  this.host.session = session;
@@ -13653,6 +13680,7 @@ var ScreamTUI = class {
13653
13680
  /** Interval handle for the periodic provider-balance refresh. */
13654
13681
  balancePollTimer;
13655
13682
  updatePrefetched;
13683
+ sessionsPrefetch;
13656
13684
  sessionManager;
13657
13685
  dialogManager;
13658
13686
  streamingUI;
@@ -13692,6 +13720,7 @@ var ScreamTUI = class {
13692
13720
  this.options = tuiOptions;
13693
13721
  this.startupNotice = startupInput.startupNotice;
13694
13722
  this.updatePrefetched = startupInput.updatePrefetched === true;
13723
+ this.sessionsPrefetch = startupInput.sessionsPrefetch;
13695
13724
  this.state = createTUIState(tuiOptions);
13696
13725
  this.harness.setSubagentModelBindings(() => this.state.appState.subagentModels);
13697
13726
  this.reverseRpcDisposers.push(...registerReverseRPCHandlers(this.approvalController, this.questionController, {
@@ -13827,7 +13856,8 @@ var ScreamTUI = class {
13827
13856
  try {
13828
13857
  const { shouldReplay } = await this.sessionManager.init({
13829
13858
  startup: this.options.startup,
13830
- workDir: this.state.appState.workDir
13859
+ workDir: this.state.appState.workDir,
13860
+ sessionsPrefetch: this.sessionsPrefetch
13831
13861
  });
13832
13862
  return shouldReplay;
13833
13863
  } catch (error) {
@@ -14142,7 +14172,7 @@ var ScreamTUI = class {
14142
14172
  const card = new OnboardingCardComponent({
14143
14173
  colors: this.state.theme.colors,
14144
14174
  onConfigure: () => {
14145
- import("./dispatch-DRdBQorE.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
14175
+ import("./dispatch-Ba8Dz_v_.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
14146
14176
  this.restoreEditor();
14147
14177
  onDone?.();
14148
14178
  });
@@ -14514,7 +14544,7 @@ function supportsAnsi() {
14514
14544
  ansiSupported = false;
14515
14545
  return false;
14516
14546
  }
14517
- async function runLoadingAnimation(theme = "dark") {
14547
+ async function runLoadingAnimation(theme, tuiConfig) {
14518
14548
  if (!supportsAnsi()) {
14519
14549
  const { cols } = getTerminalSize();
14520
14550
  if (cols >= FULL_LOGO_MIN_COLS) for (const line of LOGO) stdout.write(`${fg(...LOGO_RGB)}${line}${RESET}\n`);
@@ -14522,10 +14552,7 @@ async function runLoadingAnimation(theme = "dark") {
14522
14552
  stdout.write(`${BOLD}${fg(...THEME_PRIMARY[theme])}${t("loading.waking")}${RESET}\n`);
14523
14553
  return;
14524
14554
  }
14525
- let autoStart = false;
14526
- try {
14527
- autoStart = (await loadTuiConfig()).autoStart;
14528
- } catch {}
14555
+ let autoStart = tuiConfig.autoStart;
14529
14556
  const autoStartAtBoot = autoStart;
14530
14557
  let toggled = false;
14531
14558
  return new Promise((resolve) => {
@@ -14679,10 +14706,12 @@ async function runShell(opts, version) {
14679
14706
  });
14680
14707
  await harness.ensureConfigFile();
14681
14708
  await harness.preflight();
14709
+ const sessionsPrefetch = harness.listSessions({ workDir });
14710
+ sessionsPrefetch.catch(() => {});
14682
14711
  refreshUpdateCache().catch((error) => {
14683
14712
  log.warn("update cache refresh failed", { error });
14684
14713
  });
14685
- await runLoadingAnimation(resolvedTheme);
14714
+ await runLoadingAnimation(resolvedTheme, tuiConfig);
14686
14715
  const tui = new ScreamTUI(harness, {
14687
14716
  cliOptions: opts,
14688
14717
  tuiConfig,
@@ -14690,7 +14719,8 @@ async function runShell(opts, version) {
14690
14719
  workDir,
14691
14720
  startupNotice: configWarning,
14692
14721
  resolvedTheme,
14693
- updatePrefetched: true
14722
+ updatePrefetched: true,
14723
+ sessionsPrefetch
14694
14724
  });
14695
14725
  tui.onExit = async (exitCode = 0) => {
14696
14726
  const sessionId = tui.getCurrentSessionId();