scream-code 0.16.8 → 0.16.9

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
@@ -19,7 +19,7 @@
19
19
  </p>
20
20
 
21
21
  <p align="center">
22
- <img width="1007" height="890" alt="企业微信20260909-170226@2x" src="https://github.com/user-attachments/assets/a8c1beda-3e73-41d1-855e-7dd80a3cc0e9" />
22
+ <img width="2880" height="2880" alt="scream" src="https://github.com/user-attachments/assets/7268e848-b1b8-4540-9627-d21c94332229" />
23
23
  </p>
24
24
 
25
25
  ---
@@ -4,9 +4,9 @@ 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 { k as MemoryMemoStore } from "./src-CXmZg1VT.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 resolveScreamHome, at as toTerminalHyperlink, b as readUpdateCache, bn as TIP_ROTATION_INTERVAL_MS, c as disposeChildren, cn as appendStreamingArgsPreview, cr as resolveGlobalLogPath, d as isPlanExpandable, dn as isTodoItemShape, dr as ErrorCodes, en as SubagentSlots, er as normalizeWorkDir, f as MoonLoader, fn as parseStreamingArgs, fr as SCREAM_ERROR_INFO, 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 isScreamError, mn as stringValue, mt as handlePlanCommand, n as clearEvalPanelState, nr as readSessionIndex, on as STATUS_BULLET, or as flushDiagnosticLogs, ot as changeThinkingLevel, p as formatMemoryMemoForInjection, pn as serializeToolResultOutput, 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 log, st as getModelCycleLevel, t as dispatchInput, tr as appendSessionIndexEntry, u as isExpandable, un as formatErrorMessage, ur as isOrphanedToolCallError, 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-CNitkOqX.mjs";
9
- import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-6v2667rm.mjs";
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-CIOuINvn.mjs";
9
+ import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-XT3cOEjD.mjs";
10
10
  import { createRequire } from "node:module";
11
11
  import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
12
12
  import { access, appendFile, chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
@@ -15,10 +15,10 @@ import { WebSocket, WebSocketServer } from "ws";
15
15
  import { appendFileSync, constants, existsSync, mkdirSync, readFileSync, realpathSync, statSync, unlinkSync, writeFileSync } from "node:fs";
16
16
  import * as path$1 from "node:path";
17
17
  import path, { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
18
+ import { homedir, networkInterfaces, tmpdir } from "node:os";
18
19
  import { z } from "zod";
19
20
  import { exec, execFile, execSync, spawn, spawnSync } from "node:child_process";
20
21
  import { promisify } from "node:util";
21
- import { homedir, networkInterfaces, tmpdir } from "node:os";
22
22
  import { fileURLToPath, pathToFileURL } from "node:url";
23
23
  import { createServer } from "node:http";
24
24
  import process$1 from "node:process";
@@ -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.16.8"),
36
+ version: optionalBuildString("0.16.9"),
37
37
  channel: optionalBuildString(""),
38
38
  commit: optionalBuildString(""),
39
39
  buildTarget: optionalBuildString("darwin-arm64")
@@ -1676,20 +1676,33 @@ function resolveEditorCommand(configured) {
1676
1676
  for (const c of candidates) if (typeof c === "string" && c.trim().length > 0) return c.trim();
1677
1677
  }
1678
1678
  /**
1679
- * Launch `command` (tokenised via a shell) against a temp file seeded
1680
- * with `initialText`. Returns the edited contents on success, or
1681
- * `undefined` if the editor exited non-zero / the file disappeared.
1679
+ * Launch `command` (tokenised by the platform's command interpreter) against
1680
+ * a temp file seeded with `initialText`. Returns the edited contents on
1681
+ * success, or `undefined` if the editor exited non-zero / the file
1682
+ * disappeared.
1682
1683
  *
1683
- * The command is passed to `/bin/sh -c "<cmd> <tmpfile>"` so users can
1684
- * supply argv-style strings like `"code --wait"` or `"nvim +set ft=markdown"`.
1684
+ * The command may carry argv-style arguments (`"code --wait"`,
1685
+ * `"nvim +set ft=markdown"`), so it is handed to the interpreter the host
1686
+ * platform actually has: `/bin/sh -c` on POSIX, `cmd.exe /d /s /c` on
1687
+ * Windows. The two disagree on quoting, so each branch carries its own
1688
+ * escaping rather than borrowing the other's. `platform` is injectable so
1689
+ * both branches stay testable off their native host.
1685
1690
  */
1686
- async function editInExternalEditor(initialText, command) {
1691
+ async function editInExternalEditor(initialText, command, platform = process.platform) {
1687
1692
  const dir = await mkdtemp(join(tmpdir(), "scream-edit-"));
1688
1693
  const file = join(dir, "prompt.md");
1689
1694
  await writeFile(file, initialText, "utf-8");
1690
1695
  try {
1691
1696
  if (await new Promise((resolve, reject) => {
1692
- const child = spawn("/bin/sh", ["-c", `${command} ${shellQuote(file)}`], { stdio: "inherit" });
1697
+ const child = platform === "win32" ? spawn(windowsCommandShell(), [
1698
+ "/d",
1699
+ "/s",
1700
+ "/c",
1701
+ `"${command} ${cmdQuote(file)}"`
1702
+ ], {
1703
+ stdio: "inherit",
1704
+ windowsVerbatimArguments: true
1705
+ }) : spawn("/bin/sh", ["-c", `${command} ${shellQuote(file)}`], { stdio: "inherit" });
1693
1706
  child.on("exit", (c) => {
1694
1707
  resolve(c ?? 0);
1695
1708
  });
@@ -1703,9 +1716,18 @@ async function editInExternalEditor(initialText, command) {
1703
1716
  }).catch(() => {});
1704
1717
  }
1705
1718
  }
1719
+ /** The interpreter `cmd.exe`-style command lines run through, as Node's own
1720
+ * `shell: true` resolves it on Windows. */
1721
+ function windowsCommandShell() {
1722
+ const comspec = process.env["ComSpec"];
1723
+ return comspec !== void 0 && comspec.trim().length > 0 ? comspec : "cmd.exe";
1724
+ }
1706
1725
  function shellQuote(path) {
1707
1726
  return `'${path.replaceAll("'", "'\\''")}'`;
1708
1727
  }
1728
+ function cmdQuote(path) {
1729
+ return `"${path.replaceAll("\"", "\"\"")}"`;
1730
+ }
1709
1731
  //#endregion
1710
1732
  //#region src/tui/controllers/editor-keyboard.ts
1711
1733
  var EditorKeyboardController = class {
@@ -3789,7 +3811,7 @@ function createReplayRenderContext() {
3789
3811
  }
3790
3812
  function limitReplayRecordsByTurn(records, maxTurns) {
3791
3813
  if (maxTurns <= 0) return [];
3792
- const turnStarts = records.flatMap((record, index) => isReplayUserTurnRecord(record) ? [index] : []);
3814
+ const turnStarts = records.flatMap((record, index) => record.type === "message" && isRealUserPrompt(record.message) ? [index] : []);
3793
3815
  if (turnStarts.length <= maxTurns) return records;
3794
3816
  return records.slice(turnStarts[turnStarts.length - maxTurns]);
3795
3817
  }
@@ -3864,23 +3886,6 @@ function formatHookResultMessageForTranscript(text, fallbackEvent, blocked) {
3864
3886
  if (results.length === 0 || text.slice(lastIndex).trim().length > 0) return formatHookResultBlock(fallbackEvent, text, blocked);
3865
3887
  return results.map(({ event, body }) => formatHookResultBlock(event, body, blocked)).join("\n\n");
3866
3888
  }
3867
- function isReplayUserTurnRecord(record) {
3868
- if (record.type !== "message") return false;
3869
- const { message } = record;
3870
- if (message.role !== "user") return false;
3871
- switch (message.origin?.kind) {
3872
- case void 0:
3873
- case "user": return true;
3874
- case "skill_activation": return message.origin.trigger === "user-slash";
3875
- case "background_task":
3876
- case "compaction_summary":
3877
- case "cron_job":
3878
- case "cron_missed":
3879
- case "hook_result":
3880
- case "injection":
3881
- case "system_trigger": return false;
3882
- }
3883
- }
3884
3889
  function parseReplayToolArguments(value) {
3885
3890
  if (value === null || value.length === 0) return {};
3886
3891
  try {
@@ -14132,7 +14137,7 @@ var ScreamTUI = class {
14132
14137
  const card = new OnboardingCardComponent({
14133
14138
  colors: this.state.theme.colors,
14134
14139
  onConfigure: () => {
14135
- import("./dispatch-Du8ddILK.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
14140
+ import("./dispatch-ChbwC2I5.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
14136
14141
  this.restoreEditor();
14137
14142
  onDone?.();
14138
14143
  });
@@ -16595,23 +16600,34 @@ function removeLastTurnsBefore(messages, count, beforeSeq) {
16595
16600
  }
16596
16601
  messages.splice(0, messages.length, ...prefix, ...tail);
16597
16602
  }
16603
+ /**
16604
+ * The Web projection's anchor kind for one prompt origin.
16605
+ *
16606
+ * "Does this origin start a turn the user could `/undo`?" is the core rule, and
16607
+ * it now comes from `isRealUserPrompt` — public surface through the SDK, so this
16608
+ * projection no longer needs a copy of it. A copy is exactly what drifts from
16609
+ * the core and makes `/undo N` delete a different number of rows than the
16610
+ * history it mirrors. What is left here is the rendering split the core has no
16611
+ * opinion about: a user-typed skill turn carries no visible user row in the Web
16612
+ * transcript, so it is tagged `skill` and `/undo` removes that assistant block on
16613
+ * its own.
16614
+ *
16615
+ * Both callers ask about a *user* prompt, which is what an anchor is: the seed
16616
+ * path classifies each history message and only reads the answer for the user
16617
+ * ones, and a `turn.started` origin is the origin of the turn's prompt.
16618
+ */
16598
16619
  function classifyUndoAnchor(origin) {
16599
- if (origin === void 0 || origin === null) return "user";
16600
- if (typeof origin !== "object") return "other";
16601
- const kind = origin.kind;
16602
- if (kind === "user") return "user";
16603
- if (kind === "skill_activation" && origin.trigger === "user-slash") return "skill";
16604
- return "other";
16605
- }
16606
- /** Match the core `/undo` anchor rule without importing agent-core internals. */
16620
+ if (!isRealUserPrompt({
16621
+ role: "user",
16622
+ content: [],
16623
+ toolCalls: [],
16624
+ origin
16625
+ })) return "other";
16626
+ return origin?.kind === "skill_activation" ? "skill" : "user";
16627
+ }
16628
+ /** The core `/undo` anchor rule, applied to the whole history. */
16607
16629
  function countUndoAnchors(history) {
16608
- let count = 0;
16609
- for (const message of history) {
16610
- if (message.role !== "user") continue;
16611
- const origin = message.origin;
16612
- if (origin === void 0 || origin.kind === "user" || origin.kind === "skill_activation" && origin.trigger === "user-slash") count += 1;
16613
- }
16614
- return count;
16630
+ return history.filter(isRealUserPrompt).length;
16615
16631
  }
16616
16632
  const execFileAsync = promisify(execFile);
16617
16633
  /** Raw porcelain rows: repo-root-relative path + XY status. `getGitStatus`