scream-code 0.11.6 → 0.11.7
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.
|
@@ -7,7 +7,7 @@ import { i as __require, o as __toESM, r as __exportAll, t as __commonJSMin } fr
|
|
|
7
7
|
import "./suppress-sqlite-warning-C2VB0doZ.mjs";
|
|
8
8
|
import { C as join$1, D as resolve$1, E as relative$1, S as isAbsolute$1, T as parse$7, a as isSupportedFile, b as basename$1, i as ingestFile, r as ingestDirectory, t as multiSearch, w as normalize, x as dirname$2, y as KnowledgeStore } from "./src-BH9W5k24.mjs";
|
|
9
9
|
import { t as require_base64_js } from "./base64-js-DzVmk6Nb.mjs";
|
|
10
|
-
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-
|
|
10
|
+
import { a as setLocale, i as getLocale, n as assertScreamHostIdentity, o as t, r as createScreamDefaultHeaders, t as TextInputDialogComponent } from "./text-input-dialog-BdUmo73M.mjs";
|
|
11
11
|
import { createRequire } from "node:module";
|
|
12
12
|
import { createHash, randomBytes, randomInt, randomUUID } from "node:crypto";
|
|
13
13
|
import * as fs$1 from "node:fs/promises";
|
|
@@ -74934,7 +74934,7 @@ var BashTool = class {
|
|
|
74934
74934
|
},
|
|
74935
74935
|
approvalRule: literalRulePattern(this.name, args.command),
|
|
74936
74936
|
matchesRule: (ruleArgs) => matchesGlobRuleSubject(ruleArgs, args.command),
|
|
74937
|
-
execute: (
|
|
74937
|
+
execute: (ctx) => this.execution(args, ctx)
|
|
74938
74938
|
};
|
|
74939
74939
|
}
|
|
74940
74940
|
spawn(effectiveCwd, command) {
|
|
@@ -74954,7 +74954,8 @@ var BashTool = class {
|
|
|
74954
74954
|
};
|
|
74955
74955
|
return this.jian.execWithEnv(shellArgs, mergedEnv);
|
|
74956
74956
|
}
|
|
74957
|
-
async execution(args,
|
|
74957
|
+
async execution(args, ctx) {
|
|
74958
|
+
const { signal, onUpdate } = ctx;
|
|
74958
74959
|
const completedBg = drainCompletedBackgroundTasks();
|
|
74959
74960
|
const bgPrefix = completedBg.length > 0 ? completedBg.map((t) => `[Background task ${t.id} completed] Command: ${t.command}\nExit code: ${String(t.exitCode)} (${(t.elapsedMs / 1e3).toFixed(1)}s)\nOutput:\n${t.output}\n---\n`).join("") : "";
|
|
74960
74961
|
if (signal.aborted) return {
|
|
@@ -74993,6 +74994,14 @@ var BashTool = class {
|
|
|
74993
74994
|
} catch {}
|
|
74994
74995
|
let aborted = false;
|
|
74995
74996
|
let killed = false;
|
|
74997
|
+
let streaming = true;
|
|
74998
|
+
const forwardChunk = (kind, text) => {
|
|
74999
|
+
if (!streaming || signal.aborted || onUpdate === void 0) return;
|
|
75000
|
+
onUpdate({
|
|
75001
|
+
kind,
|
|
75002
|
+
text
|
|
75003
|
+
});
|
|
75004
|
+
};
|
|
74996
75005
|
const killProc = async () => {
|
|
74997
75006
|
if (killed) return;
|
|
74998
75007
|
killed = true;
|
|
@@ -75030,17 +75039,39 @@ var BashTool = class {
|
|
|
75030
75039
|
return artifactPath;
|
|
75031
75040
|
} });
|
|
75032
75041
|
if (bgPrefix.length > 0) builder.write(bgPrefix);
|
|
75033
|
-
const completionPromise = Promise.all([Promise.all([readStreamIntoBuilder(proc.stdout, builder), readStreamIntoBuilder(proc.stderr, builder)]), proc.wait()]).then(([, exitCode]) => ({
|
|
75042
|
+
const completionPromise = Promise.all([Promise.all([readStreamIntoBuilder(proc.stdout, builder, (text) => forwardChunk("stdout", text)), readStreamIntoBuilder(proc.stderr, builder, (text) => forwardChunk("stderr", text))]), proc.wait()]).then(([, exitCode]) => ({
|
|
75034
75043
|
timedOut: false,
|
|
75035
75044
|
exitCode
|
|
75036
75045
|
}));
|
|
75037
75046
|
const raceResult = timeoutMs !== void 0 ? await Promise.race([completionPromise, timeoutPromise]) : await completionPromise;
|
|
75038
75047
|
if (raceResult.timedOut) {
|
|
75048
|
+
streaming = false;
|
|
75039
75049
|
const timeoutLabel = timeoutMs % 1e3 === 0 ? `${String(timeoutMs / 1e3)}s` : `${String(timeoutMs)}ms`;
|
|
75040
75050
|
const taskId = createBackgroundTask(command, completionPromise.then(({ exitCode }) => ({
|
|
75041
75051
|
exitCode,
|
|
75042
75052
|
output: builder.toString()
|
|
75043
75053
|
})));
|
|
75054
|
+
if (onUpdate !== void 0) completionPromise.then(({ exitCode }) => {
|
|
75055
|
+
onUpdate({
|
|
75056
|
+
kind: "custom",
|
|
75057
|
+
customKind: "background.task.terminated",
|
|
75058
|
+
customData: {
|
|
75059
|
+
id: taskId,
|
|
75060
|
+
command,
|
|
75061
|
+
exitCode
|
|
75062
|
+
}
|
|
75063
|
+
});
|
|
75064
|
+
}, () => {
|
|
75065
|
+
onUpdate({
|
|
75066
|
+
kind: "custom",
|
|
75067
|
+
customKind: "background.task.terminated",
|
|
75068
|
+
customData: {
|
|
75069
|
+
id: taskId,
|
|
75070
|
+
command,
|
|
75071
|
+
exitCode: -1
|
|
75072
|
+
}
|
|
75073
|
+
});
|
|
75074
|
+
});
|
|
75044
75075
|
const outputSoFar = builder.toString();
|
|
75045
75076
|
return {
|
|
75046
75077
|
output: `Command timed out after ${timeoutLabel} but is still running in the background (task: ${taskId}).\nOutput so far (${String(builder.nChars)} chars):\n${outputSoFar}\n---\nThe command will complete in the background. The result will be included in your next Bash call.`,
|
|
@@ -75138,13 +75169,33 @@ human_shell_hint: Tell the human to run /tasks to open the interactive backgroun
|
|
|
75138
75169
|
return builder.ok("Background task started", { brief: `Started ${taskId}` });
|
|
75139
75170
|
}
|
|
75140
75171
|
};
|
|
75141
|
-
|
|
75172
|
+
const LIVE_OUTPUT_FLUSH_MS = 100;
|
|
75173
|
+
async function readStreamIntoBuilder(stream, builder, onChunk) {
|
|
75142
75174
|
const decoder = new StringDecoder("utf8");
|
|
75175
|
+
let pending = "";
|
|
75176
|
+
let lastFlush = 0;
|
|
75177
|
+
const flush = (force) => {
|
|
75178
|
+
if (pending.length === 0) return;
|
|
75179
|
+
if (!force && Date.now() - lastFlush < LIVE_OUTPUT_FLUSH_MS) return;
|
|
75180
|
+
onChunk?.(pending);
|
|
75181
|
+
pending = "";
|
|
75182
|
+
lastFlush = Date.now();
|
|
75183
|
+
};
|
|
75143
75184
|
for await (const chunk of stream) {
|
|
75144
75185
|
const buf = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
75145
|
-
|
|
75186
|
+
const text = decoder.write(buf);
|
|
75187
|
+
builder.write(text);
|
|
75188
|
+
if (onChunk !== void 0) {
|
|
75189
|
+
pending += text;
|
|
75190
|
+
flush(false);
|
|
75191
|
+
}
|
|
75192
|
+
}
|
|
75193
|
+
const tail = decoder.end();
|
|
75194
|
+
builder.write(tail);
|
|
75195
|
+
if (onChunk !== void 0) {
|
|
75196
|
+
pending += tail;
|
|
75197
|
+
flush(true);
|
|
75146
75198
|
}
|
|
75147
|
-
builder.write(decoder.end());
|
|
75148
75199
|
}
|
|
75149
75200
|
function shellQuote$1(s) {
|
|
75150
75201
|
return `'${s.replaceAll("'", "'\\''")}'`;
|
|
@@ -120602,7 +120653,7 @@ function optionalBuildString(value) {
|
|
|
120602
120653
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
120603
120654
|
}
|
|
120604
120655
|
const SCREAM_BUILD_INFO = {
|
|
120605
|
-
version: optionalBuildString("0.11.
|
|
120656
|
+
version: optionalBuildString("0.11.7"),
|
|
120606
120657
|
channel: optionalBuildString(""),
|
|
120607
120658
|
commit: optionalBuildString(""),
|
|
120608
120659
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -120872,6 +120923,8 @@ const TuiLikePreferencesSchema = z.object({
|
|
|
120872
120923
|
const TuiConfigFileSchema = z.object({
|
|
120873
120924
|
theme: TuiThemeSchema.optional(),
|
|
120874
120925
|
language: z.enum(["zh", "en"]).optional(),
|
|
120926
|
+
/** Auto-enter the welcome page after the loading splash finishes. */
|
|
120927
|
+
autoStart: z.boolean().optional(),
|
|
120875
120928
|
editor: z.object({ command: z.string().optional() }).optional(),
|
|
120876
120929
|
notifications: z.object({
|
|
120877
120930
|
enabled: z.boolean().optional(),
|
|
@@ -120887,6 +120940,7 @@ const TuiConfigFileSchema = z.object({
|
|
|
120887
120940
|
const TuiConfigSchema = z.object({
|
|
120888
120941
|
theme: TuiThemeSchema,
|
|
120889
120942
|
language: z.enum(["zh", "en"]),
|
|
120943
|
+
autoStart: z.boolean(),
|
|
120890
120944
|
editorCommand: z.string().nullable(),
|
|
120891
120945
|
notifications: NotificationsConfigSchema,
|
|
120892
120946
|
like: TuiLikePreferencesSchema,
|
|
@@ -120903,6 +120957,7 @@ const DEFAULT_NOTIFICATIONS_CONFIG = {
|
|
|
120903
120957
|
const DEFAULT_TUI_CONFIG = TuiConfigSchema.parse({
|
|
120904
120958
|
theme: "auto",
|
|
120905
120959
|
language: getLocale(),
|
|
120960
|
+
autoStart: false,
|
|
120906
120961
|
editorCommand: null,
|
|
120907
120962
|
notifications: DEFAULT_NOTIFICATIONS_CONFIG,
|
|
120908
120963
|
like: {},
|
|
@@ -120955,6 +121010,7 @@ function normalizeTuiConfig(config) {
|
|
|
120955
121010
|
return TuiConfigSchema.parse({
|
|
120956
121011
|
theme: config.theme ?? DEFAULT_TUI_CONFIG.theme,
|
|
120957
121012
|
language: config.language ?? DEFAULT_TUI_CONFIG.language,
|
|
121013
|
+
autoStart: config.autoStart ?? DEFAULT_TUI_CONFIG.autoStart,
|
|
120958
121014
|
editorCommand: command === void 0 || command.length === 0 ? null : command,
|
|
120959
121015
|
notifications: {
|
|
120960
121016
|
enabled: config.notifications?.enabled ?? DEFAULT_NOTIFICATIONS_CONFIG.enabled,
|
|
@@ -120998,6 +121054,7 @@ function renderTuiConfig(config) {
|
|
|
120998
121054
|
|
|
120999
121055
|
theme = "${config.theme}" # "auto" | "dark" | "light"
|
|
121000
121056
|
language = "${config.language}" # "zh" | "en"
|
|
121057
|
+
autoStart = ${String(config.autoStart)} # true = auto-enter welcome after loading
|
|
121001
121058
|
|
|
121002
121059
|
[editor]
|
|
121003
121060
|
command = "${escapeTomlBasicString(config.editorCommand ?? "")}" # Empty uses $VISUAL / $EDITOR
|
|
@@ -123813,14 +123870,28 @@ function formatTokenCount(n) {
|
|
|
123813
123870
|
function safeUsage(usage) {
|
|
123814
123871
|
return safeUsageRatio(usage);
|
|
123815
123872
|
}
|
|
123873
|
+
const CONTEXT_BAR_WIDTH = 10;
|
|
123874
|
+
const CONTEXT_BAR_FILLED = "▰";
|
|
123875
|
+
const CONTEXT_BAR_EMPTY = "▱";
|
|
123876
|
+
/**
|
|
123877
|
+
* Half-block progress bar for context usage: `▰▰▰▱▱▱▱▱▱▱` (10 cells).
|
|
123878
|
+
* Filled cells are rounded from the clamped ratio, so 0% is all-empty and
|
|
123879
|
+
* >=100% is all-filled; NaN/undefined coerce through safeUsageRatio first.
|
|
123880
|
+
*/
|
|
123881
|
+
function formatContextBar(usage, width = CONTEXT_BAR_WIDTH) {
|
|
123882
|
+
const clamped = Math.min(1, Math.max(0, safeUsageRatio(usage)));
|
|
123883
|
+
const filled = Math.round(clamped * width);
|
|
123884
|
+
return CONTEXT_BAR_FILLED.repeat(filled) + CONTEXT_BAR_EMPTY.repeat(width - filled);
|
|
123885
|
+
}
|
|
123816
123886
|
function formatContextStatus(usage, tokens, maxTokens) {
|
|
123817
123887
|
const pct = `${(safeUsage(usage) * 100).toFixed(1)}%`;
|
|
123888
|
+
const barAndPct = `${formatContextBar(usage)} ${pct}`;
|
|
123818
123889
|
if (maxTokens && maxTokens > 0 && tokens !== void 0) return t("footer.context", {
|
|
123819
|
-
pct,
|
|
123890
|
+
pct: barAndPct,
|
|
123820
123891
|
tokens: formatTokenCount(tokens),
|
|
123821
123892
|
maxTokens: formatTokenCount(maxTokens)
|
|
123822
123893
|
});
|
|
123823
|
-
return t("footer.context_short", { pct });
|
|
123894
|
+
return t("footer.context_short", { pct: barAndPct });
|
|
123824
123895
|
}
|
|
123825
123896
|
/** Format goal wall-clock duration compactly: `3m`, `1m30s`, `45s`. */
|
|
123826
123897
|
function formatGoalDuration(ms) {
|
|
@@ -124093,6 +124164,7 @@ async function applyLanguageChoice(host, locale) {
|
|
|
124093
124164
|
setLocale(locale);
|
|
124094
124165
|
host.state.appState.language = locale;
|
|
124095
124166
|
await saveTuiConfig({
|
|
124167
|
+
...await loadTuiConfig(),
|
|
124096
124168
|
theme: host.state.appState.theme,
|
|
124097
124169
|
language: locale,
|
|
124098
124170
|
editorCommand: host.state.appState.editorCommand,
|
|
@@ -125159,6 +125231,7 @@ async function applyEditorChoice(host, value) {
|
|
|
125159
125231
|
const editorCommand = value.length > 0 ? value : null;
|
|
125160
125232
|
try {
|
|
125161
125233
|
await saveTuiConfig({
|
|
125234
|
+
...await loadTuiConfig(),
|
|
125162
125235
|
theme: host.state.appState.theme,
|
|
125163
125236
|
language: host.state.appState.language,
|
|
125164
125237
|
editorCommand,
|
|
@@ -125344,6 +125417,7 @@ async function applyThemeChoice(host, theme) {
|
|
|
125344
125417
|
}
|
|
125345
125418
|
try {
|
|
125346
125419
|
await saveTuiConfig({
|
|
125420
|
+
...await loadTuiConfig(),
|
|
125347
125421
|
theme,
|
|
125348
125422
|
language: host.state.appState.language,
|
|
125349
125423
|
editorCommand: host.state.appState.editorCommand,
|
|
@@ -126121,7 +126195,7 @@ async function guidedGoalSetup(host) {
|
|
|
126121
126195
|
host.showNotice(t("goal.storm_breaker"), t("goal.conflict_loop"));
|
|
126122
126196
|
return;
|
|
126123
126197
|
}
|
|
126124
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
126198
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-Ct-Yn67a.mjs");
|
|
126125
126199
|
const initialDesc = await promptText(host, TextInputDialogComponent, {
|
|
126126
126200
|
title: t("goal.setup_title_initial"),
|
|
126127
126201
|
subtitle: t("goal.setup_desc_hint"),
|
|
@@ -126142,7 +126216,7 @@ async function guidedGoalSetup(host) {
|
|
|
126142
126216
|
await showGoalConfigWizard(host, session, confirmed.trim() || objective, false);
|
|
126143
126217
|
}
|
|
126144
126218
|
async function showGoalConfigWizard(host, session, objective, replace) {
|
|
126145
|
-
const { TextInputDialogComponent } = await import("./text-input-dialog-
|
|
126219
|
+
const { TextInputDialogComponent } = await import("./text-input-dialog-Ct-Yn67a.mjs");
|
|
126146
126220
|
const turnInput = await promptNumber(host, TextInputDialogComponent, {
|
|
126147
126221
|
title: t("goal.wizard_title", { objective }),
|
|
126148
126222
|
subtitle: t("goal.budget_turns_hint"),
|
|
@@ -128529,7 +128603,7 @@ const globGlance = (_toolCall, result, colors) => {
|
|
|
128529
128603
|
const more = names.length - GLANCE_SAMPLES;
|
|
128530
128604
|
return `${head}${shown}${more > 0 ? dim(` (+${String(more)})`) : ""}`;
|
|
128531
128605
|
}).join(dim(" "));
|
|
128532
|
-
const extLine = [...countExtensions(lines).entries()].
|
|
128606
|
+
const extLine = [...countExtensions(lines).entries()].toSorted((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_EXTENSION_COUNTS).map(([ext, count]) => `${dim(ext)}:${dim(` ${String(count)}`)}`).join(dim(", "));
|
|
128533
128607
|
if (extLine.length === 0) return dirLine;
|
|
128534
128608
|
return `${dirLine}${dim(" ")}${extLine}`;
|
|
128535
128609
|
};
|
|
@@ -128559,8 +128633,56 @@ const readGlance = (toolCall, result, colors) => {
|
|
|
128559
128633
|
if (parts.length === 0) return "";
|
|
128560
128634
|
return parts.join(dim(" · "));
|
|
128561
128635
|
};
|
|
128636
|
+
/**
|
|
128637
|
+
* Parse the fixed WebSearch output protocol emitted by
|
|
128638
|
+
* `web-search.ts` (`Title: …` / `Date: …` / `URL: …` / `Snippet: …`,
|
|
128639
|
+
* entries separated by `---`) into structured entries so the collapsed
|
|
128640
|
+
* card can show a title/URL glance instead of a bare "N results" chip.
|
|
128641
|
+
*/
|
|
128642
|
+
function parseWebSearchOutput(output) {
|
|
128643
|
+
const entries = [];
|
|
128644
|
+
let title;
|
|
128645
|
+
let url;
|
|
128646
|
+
let inSnippet = false;
|
|
128647
|
+
for (const line of output.split("\n")) {
|
|
128648
|
+
if (line.startsWith("---")) {
|
|
128649
|
+
if (title !== void 0 || url !== void 0) entries.push({
|
|
128650
|
+
title: title ?? "",
|
|
128651
|
+
url: url ?? ""
|
|
128652
|
+
});
|
|
128653
|
+
title = void 0;
|
|
128654
|
+
url = void 0;
|
|
128655
|
+
inSnippet = false;
|
|
128656
|
+
continue;
|
|
128657
|
+
}
|
|
128658
|
+
if (inSnippet) continue;
|
|
128659
|
+
if (line.startsWith("Snippet: ")) inSnippet = true;
|
|
128660
|
+
else if (line.startsWith("Title: ")) title = line.slice(7);
|
|
128661
|
+
else if (line.startsWith("URL: ")) url = line.slice(5);
|
|
128662
|
+
}
|
|
128663
|
+
if (title !== void 0 || url !== void 0) entries.push({
|
|
128664
|
+
title: title ?? "",
|
|
128665
|
+
url: url ?? ""
|
|
128666
|
+
});
|
|
128667
|
+
return entries;
|
|
128668
|
+
}
|
|
128669
|
+
function truncateText(text, max = 60) {
|
|
128670
|
+
return text.length <= max ? text : `${text.slice(0, max - 1)}…`;
|
|
128671
|
+
}
|
|
128672
|
+
const webSearchGlance = (_toolCall, result, colors) => {
|
|
128673
|
+
const entries = parseWebSearchOutput(result.output);
|
|
128674
|
+
if (entries.length === 0) return "";
|
|
128675
|
+
const titleColor = chalk.hex(colors.roleTool);
|
|
128676
|
+
const dim = chalk.dim;
|
|
128677
|
+
const lines = entries.slice(0, GLANCE_SAMPLES).map((e) => {
|
|
128678
|
+
return [e.title.length > 0 ? titleColor(truncateText(e.title)) : "", e.url.length > 0 ? dim(truncateText(e.url)) : ""].filter((s) => s.length > 0).join(dim(" — "));
|
|
128679
|
+
});
|
|
128680
|
+
const remaining = entries.length - GLANCE_SAMPLES;
|
|
128681
|
+
if (remaining > 0) lines.push(dim(`+${String(remaining)} more`));
|
|
128682
|
+
return lines.join("\n");
|
|
128683
|
+
};
|
|
128562
128684
|
const fetchSummary = withGlance(null);
|
|
128563
|
-
const webSearchSummary = withGlance(
|
|
128685
|
+
const webSearchSummary = withGlance(webSearchGlance);
|
|
128564
128686
|
const thinkSummary = withGlance(null);
|
|
128565
128687
|
const editSummary = withGlance(null);
|
|
128566
128688
|
const writeSummary = withGlance(null);
|
|
@@ -128608,6 +128730,7 @@ const STREAMING_PROGRESS_INTERVAL_MS = 1e3;
|
|
|
128608
128730
|
const SUBAGENT_ELAPSED_INTERVAL_MS = 1e3;
|
|
128609
128731
|
const PROGRESS_URL_RE = /https?:\/\/\S+/g;
|
|
128610
128732
|
const MAX_PROGRESS_LINE_CHARS = 1e4;
|
|
128733
|
+
const MAX_LIVE_OUTPUT_CHARS = 5e4;
|
|
128611
128734
|
function backgroundFailureMessage(status) {
|
|
128612
128735
|
switch (status) {
|
|
128613
128736
|
case "lost": return t("toolcall.bg_agent_lost");
|
|
@@ -128926,6 +129049,10 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
128926
129049
|
subagentEndedAtMs;
|
|
128927
129050
|
progressLines = [];
|
|
128928
129051
|
static MAX_PROGRESS_LINES = 24;
|
|
129052
|
+
/** Live stdout/stderr accumulated via appendLiveOutput while the tool runs. */
|
|
129053
|
+
liveOutput = "";
|
|
129054
|
+
/** Session permission mode at card creation; drives ExitPlanMode chip wording. */
|
|
129055
|
+
permissionMode;
|
|
128929
129056
|
writeStreamContentStart = -1;
|
|
128930
129057
|
writeStreamNlScanOffset = 0;
|
|
128931
129058
|
writeStreamNlCount = 0;
|
|
@@ -128988,6 +129115,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
128988
129115
|
setResult(result) {
|
|
128989
129116
|
this.result = result;
|
|
128990
129117
|
this.progressLines = [];
|
|
129118
|
+
this.liveOutput = "";
|
|
128991
129119
|
this.finalizeSubagentElapsedIfNeeded();
|
|
128992
129120
|
this.syncStreamingProgressTimer();
|
|
128993
129121
|
this.syncSubagentElapsedTimer();
|
|
@@ -129018,6 +129146,31 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
129018
129146
|
this.notifySnapshotChange();
|
|
129019
129147
|
this.ui?.requestRender();
|
|
129020
129148
|
}
|
|
129149
|
+
/**
|
|
129150
|
+
* Append live stdout/stderr from a running tool (Bash). Kept separate
|
|
129151
|
+
* from appendProgress so streaming command output renders with the same
|
|
129152
|
+
* tail-preview styling as the final result. The buffer is capped and
|
|
129153
|
+
* tail-preserving so a runaway command cannot grow the box unboundedly;
|
|
129154
|
+
* the block is dropped entirely once the real result lands.
|
|
129155
|
+
*/
|
|
129156
|
+
appendLiveOutput(text) {
|
|
129157
|
+
if (this.result !== void 0 || text.length === 0) return;
|
|
129158
|
+
this.liveOutput += text;
|
|
129159
|
+
if (this.liveOutput.length > MAX_LIVE_OUTPUT_CHARS) this.liveOutput = `[...truncated]\n${this.liveOutput.slice(this.liveOutput.length - MAX_LIVE_OUTPUT_CHARS)}`;
|
|
129160
|
+
this.rebuildContent();
|
|
129161
|
+
this.notifySnapshotChange();
|
|
129162
|
+
this.ui?.requestRender();
|
|
129163
|
+
}
|
|
129164
|
+
/**
|
|
129165
|
+
* Records the session permission mode so ExitPlanMode can render an
|
|
129166
|
+
* honest "auto-approved" chip when the plan passed without user review.
|
|
129167
|
+
*/
|
|
129168
|
+
setPermissionMode(mode) {
|
|
129169
|
+
if (this.permissionMode === mode) return;
|
|
129170
|
+
this.permissionMode = mode;
|
|
129171
|
+
this.headerText.setText(this.buildHeader());
|
|
129172
|
+
this.ui?.requestRender();
|
|
129173
|
+
}
|
|
129021
129174
|
dispose() {
|
|
129022
129175
|
if (this.disposed) return;
|
|
129023
129176
|
this.disposed = true;
|
|
@@ -129433,6 +129586,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
129433
129586
|
if (!isFinished || result === void 0 || result.is_error === true) return label;
|
|
129434
129587
|
const outcome = interpretExitPlanModeOutcome(result.output);
|
|
129435
129588
|
if (outcome.kind === "approved") {
|
|
129589
|
+
if (this.permissionMode === "auto" && outcome.chosen === void 0) return `${label}${chalk.hex(colors.warning)(` · ${t("toolcall.auto_approved")}`)}`;
|
|
129436
129590
|
const chipText = outcome.chosen !== void 0 && outcome.chosen.length > 0 ? t("toolcall.approved", { chosen: outcome.chosen }) : t("toolcall.approved_label");
|
|
129437
129591
|
return `${label}${chalk.hex(colors.success)(` · ${chipText}`)}`;
|
|
129438
129592
|
}
|
|
@@ -129465,6 +129619,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
129465
129619
|
this.markDirty();
|
|
129466
129620
|
while (this.children.length > this.callPreviewEndIndex) this.children.pop();
|
|
129467
129621
|
this.buildProgressBlock();
|
|
129622
|
+
this.buildLiveOutputBlock();
|
|
129468
129623
|
this.buildContent();
|
|
129469
129624
|
this.buildSubagentBlock();
|
|
129470
129625
|
}
|
|
@@ -129474,6 +129629,7 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
129474
129629
|
this.buildCallPreview();
|
|
129475
129630
|
this.callPreviewEndIndex = this.children.length;
|
|
129476
129631
|
this.buildProgressBlock();
|
|
129632
|
+
this.buildLiveOutputBlock();
|
|
129477
129633
|
this.buildContent();
|
|
129478
129634
|
this.buildSubagentBlock();
|
|
129479
129635
|
}
|
|
@@ -129503,6 +129659,25 @@ var ToolCallComponent = class ToolCallComponent extends CachedContainer {
|
|
|
129503
129659
|
this.addChild(new Text(styled, 2, 0));
|
|
129504
129660
|
}
|
|
129505
129661
|
}
|
|
129662
|
+
/**
|
|
129663
|
+
* Render live stdout/stderr while the tool is still running. Reuses the
|
|
129664
|
+
* shell result renderer so the streaming tail matches the final output's
|
|
129665
|
+
* preview styling (including ctrl+o expansion); the block is skipped once
|
|
129666
|
+
* the real result has landed.
|
|
129667
|
+
*/
|
|
129668
|
+
buildLiveOutputBlock() {
|
|
129669
|
+
if (this.result !== void 0) return;
|
|
129670
|
+
if (this.liveOutput.length === 0) return;
|
|
129671
|
+
const components = shellExecutionResultRenderer(this.toolCall, {
|
|
129672
|
+
tool_call_id: this.toolCall.id,
|
|
129673
|
+
output: this.liveOutput,
|
|
129674
|
+
is_error: false
|
|
129675
|
+
}, {
|
|
129676
|
+
expanded: this.expanded,
|
|
129677
|
+
colors: this.colors
|
|
129678
|
+
});
|
|
129679
|
+
for (const component of components) this.addChild(component);
|
|
129680
|
+
}
|
|
129506
129681
|
buildSubagentBlock() {
|
|
129507
129682
|
if (this.subagentAgentId === void 0 && this.ongoingSubCalls.size === 0 && this.finishedSubCalls.length === 0 && this.subagentText.length === 0 && this.subagentPhase === void 0 && this.backgroundTaskTerminalPhase === void 0) return;
|
|
129508
129683
|
if (this.isSingleSubagentView()) {
|
|
@@ -136525,12 +136700,32 @@ var SessionEventHandler = class {
|
|
|
136525
136700
|
streamingUI.scheduleFlush();
|
|
136526
136701
|
}
|
|
136527
136702
|
handleToolProgress(event) {
|
|
136528
|
-
if (event.update.kind
|
|
136703
|
+
if (event.update.kind === "custom" && event.update.customKind === "background.task.terminated") {
|
|
136704
|
+
const data = event.update.customData;
|
|
136705
|
+
const id = typeof data?.id === "string" ? data.id : "";
|
|
136706
|
+
const command = typeof data?.command === "string" ? data.command : "";
|
|
136707
|
+
const exitCode = typeof data?.exitCode === "number" ? data.exitCode : -1;
|
|
136708
|
+
const preview = command.length > 60 ? `${command.slice(0, 59)}…` : command;
|
|
136709
|
+
if (exitCode === 0) this.host.showNotice(t("bash.background_completed", {
|
|
136710
|
+
id,
|
|
136711
|
+
command: preview
|
|
136712
|
+
}));
|
|
136713
|
+
else this.host.showNotice(t("bash.background_failed", {
|
|
136714
|
+
id,
|
|
136715
|
+
command: preview,
|
|
136716
|
+
exitCode: String(exitCode)
|
|
136717
|
+
}));
|
|
136718
|
+
return;
|
|
136719
|
+
}
|
|
136529
136720
|
const text = event.update.text;
|
|
136530
136721
|
if (text === void 0 || text.length === 0) return;
|
|
136531
136722
|
const tc = this.host.streamingUI.getToolComponent(event.toolCallId);
|
|
136532
136723
|
if (tc === void 0) return;
|
|
136533
|
-
|
|
136724
|
+
if (event.update.kind === "status") {
|
|
136725
|
+
tc.appendProgress(text);
|
|
136726
|
+
return;
|
|
136727
|
+
}
|
|
136728
|
+
if (event.update.kind === "stdout" || event.update.kind === "stderr") tc.appendLiveOutput(text);
|
|
136534
136729
|
}
|
|
136535
136730
|
handleToolResult(event) {
|
|
136536
136731
|
const { streamingUI } = this.host;
|
|
@@ -138146,6 +138341,7 @@ var StreamingUIController = class {
|
|
|
138146
138341
|
}
|
|
138147
138342
|
const { state } = this.host;
|
|
138148
138343
|
const tc = new ToolCallComponent(toolCall, void 0, state.theme.colors, state.ui, state.theme.markdownTheme, state.appState.workDir);
|
|
138344
|
+
tc.setPermissionMode(state.appState.permissionMode);
|
|
138149
138345
|
const entry = {
|
|
138150
138346
|
id: nextTranscriptId(),
|
|
138151
138347
|
kind: "tool_call",
|
|
@@ -138231,6 +138427,7 @@ var StreamingUIController = class {
|
|
|
138231
138427
|
}
|
|
138232
138428
|
if (matchedCall?.name === "AskUserQuestion") {
|
|
138233
138429
|
const completed = new ToolCallComponent(matchedCall, result, state.theme.colors, state.ui, state.theme.markdownTheme, state.appState.workDir);
|
|
138430
|
+
completed.setPermissionMode(state.appState.permissionMode);
|
|
138234
138431
|
if (state.toolOutputExpanded) completed.setExpanded(true);
|
|
138235
138432
|
if (state.planExpanded) completed.setPlanExpanded(true);
|
|
138236
138433
|
const entry = {
|
|
@@ -145768,14 +145965,20 @@ function supportsAnsi() {
|
|
|
145768
145965
|
ansiSupported = false;
|
|
145769
145966
|
return false;
|
|
145770
145967
|
}
|
|
145771
|
-
function runLoadingAnimation(theme = "dark") {
|
|
145968
|
+
async function runLoadingAnimation(theme = "dark") {
|
|
145772
145969
|
if (!supportsAnsi()) {
|
|
145773
145970
|
const { cols } = getTerminalSize();
|
|
145774
145971
|
if (cols >= FULL_LOGO_MIN_COLS) for (const line of LOGO) stdout.write(`${fg(...LOGO_RGB)}${line}${RESET}\n`);
|
|
145775
145972
|
else for (const line of COMPACT_LOGO) stdout.write(`${fg(...BLOCK_RGB)}${line}${RESET}\n`);
|
|
145776
145973
|
stdout.write(`${BOLD}${fg(...THEME_PRIMARY[theme])}${t("loading.waking")}${RESET}\n`);
|
|
145777
|
-
return
|
|
145974
|
+
return;
|
|
145778
145975
|
}
|
|
145976
|
+
let autoStart = false;
|
|
145977
|
+
try {
|
|
145978
|
+
autoStart = (await loadTuiConfig()).autoStart;
|
|
145979
|
+
} catch {}
|
|
145980
|
+
const autoStartAtBoot = autoStart;
|
|
145981
|
+
let toggled = false;
|
|
145779
145982
|
return new Promise((resolve) => {
|
|
145780
145983
|
if (process$1.platform !== "win32") stdout.write("\x1B[?1049h");
|
|
145781
145984
|
stdout.write("\x1B[2J");
|
|
@@ -145809,7 +146012,9 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
145809
146012
|
else lines.push(centerPad(`${BOLD}${fg(...breatheColor)}${t("loading.press_enter")}${RESET}`, cols));
|
|
145810
146013
|
lines.push("");
|
|
145811
146014
|
lines.push("");
|
|
145812
|
-
|
|
146015
|
+
const rightText = toggled ? autoStart ? t("loading.auto_start_on") : t("loading.auto_start_off") : t("loading.auto_start_hint");
|
|
146016
|
+
const hint = `${t("loading.quit_hint")} ${rightText}`;
|
|
146017
|
+
lines.push(centerPad(`${fg(...DIM_RGB)}${hint}${RESET}`, cols));
|
|
145813
146018
|
while (lines.length < rows) lines.push("");
|
|
145814
146019
|
stdout.write("\x1B[H");
|
|
145815
146020
|
stdout.write(lines.join("\n"));
|
|
@@ -145830,6 +146035,20 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
145830
146035
|
interrupt();
|
|
145831
146036
|
return;
|
|
145832
146037
|
}
|
|
146038
|
+
if (key === "") {
|
|
146039
|
+
toggled = true;
|
|
146040
|
+
autoStart = !autoStart;
|
|
146041
|
+
(async () => {
|
|
146042
|
+
try {
|
|
146043
|
+
await saveTuiConfig({
|
|
146044
|
+
...await loadTuiConfig(),
|
|
146045
|
+
autoStart
|
|
146046
|
+
});
|
|
146047
|
+
} catch {}
|
|
146048
|
+
})();
|
|
146049
|
+
render();
|
|
146050
|
+
return;
|
|
146051
|
+
}
|
|
145833
146052
|
if ((key === "\r" || key === "\n") && phase === "ready") {
|
|
145834
146053
|
cleanup();
|
|
145835
146054
|
resolve();
|
|
@@ -145875,6 +146094,10 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
145875
146094
|
}).then(() => {
|
|
145876
146095
|
phase = "ready";
|
|
145877
146096
|
render();
|
|
146097
|
+
if (autoStartAtBoot) setTimeout(() => {
|
|
146098
|
+
cleanup();
|
|
146099
|
+
resolve();
|
|
146100
|
+
}, 350);
|
|
145878
146101
|
});
|
|
145879
146102
|
});
|
|
145880
146103
|
}
|
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-
|
|
9
|
+
(await import("./app-D95_TREY.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);
|
|
@@ -221,6 +221,9 @@ const dictionaries = {
|
|
|
221
221
|
"loading.waking": "正在唤醒核心...",
|
|
222
222
|
"loading.press_enter": "按下 ENTER 唤醒核心",
|
|
223
223
|
"loading.quit_hint": "按住 Ctrl+C 即可退出 Scream Code",
|
|
224
|
+
"loading.auto_start_hint": "Ctrl+E 即可切换一键启动",
|
|
225
|
+
"loading.auto_start_on": "Ctrl+E 即可切换一键启动(默认启动开)",
|
|
226
|
+
"loading.auto_start_off": "Ctrl+E 即可切换一键启动(默认启动关)",
|
|
224
227
|
"language.picker_title": "语言 / Language",
|
|
225
228
|
"language.picker_hint": "↑↓ 选择 · Enter 确认 · Esc 取消",
|
|
226
229
|
"language.unchanged": "语言未更改:\"{locale}\"。",
|
|
@@ -593,6 +596,7 @@ const dictionaries = {
|
|
|
593
596
|
"toolcall.current_plan": "当前计划",
|
|
594
597
|
"toolcall.approved": "已批准:{chosen}",
|
|
595
598
|
"toolcall.approved_label": "已批准",
|
|
599
|
+
"toolcall.auto_approved": "自动批准",
|
|
596
600
|
"toolcall.input_unavailable": "无法收集你的输入",
|
|
597
601
|
"toolcall.input_collected": "已收集你的答案",
|
|
598
602
|
"toolcall.waiting_input": "等待你的输入",
|
|
@@ -803,6 +807,8 @@ const dictionaries = {
|
|
|
803
807
|
"export.session_title": "# Scream 会话导出",
|
|
804
808
|
"bgtask.agent_task": "代理任务",
|
|
805
809
|
"bgtask.bash_task": "bash 任务",
|
|
810
|
+
"bash.background_completed": "后台任务 {id} 已完成:{command}",
|
|
811
|
+
"bash.background_failed": "后台任务 {id} 执行失败(退出码 {exitCode}):{command}",
|
|
806
812
|
"bgtask.started_bg": "{subject} 已在后台启动",
|
|
807
813
|
"bgtask.awaiting_approval": "{subject} 等待审批",
|
|
808
814
|
"bgtask.completed_bg": "{subject} 已在后台完成",
|
|
@@ -1252,6 +1258,9 @@ const dictionaries = {
|
|
|
1252
1258
|
"loading.waking": "Waking core...",
|
|
1253
1259
|
"loading.press_enter": "Press ENTER to wake core",
|
|
1254
1260
|
"loading.quit_hint": "Hold Ctrl+C to quit Scream Code",
|
|
1261
|
+
"loading.auto_start_hint": "Ctrl+E to toggle auto-start",
|
|
1262
|
+
"loading.auto_start_on": "Ctrl+E to toggle auto-start (ON)",
|
|
1263
|
+
"loading.auto_start_off": "Ctrl+E to toggle auto-start (OFF)",
|
|
1255
1264
|
"language.picker_title": "Language / 语言",
|
|
1256
1265
|
"language.picker_hint": "↑↓ Select · Enter confirm · Esc cancel",
|
|
1257
1266
|
"language.unchanged": "Language unchanged: \"{locale}\".",
|
|
@@ -1624,6 +1633,7 @@ const dictionaries = {
|
|
|
1624
1633
|
"toolcall.current_plan": "Current Plan",
|
|
1625
1634
|
"toolcall.approved": "Approved: {chosen}",
|
|
1626
1635
|
"toolcall.approved_label": "Approved",
|
|
1636
|
+
"toolcall.auto_approved": "Auto-approved",
|
|
1627
1637
|
"toolcall.input_unavailable": "Could not collect your input",
|
|
1628
1638
|
"toolcall.input_collected": "Collected your answer",
|
|
1629
1639
|
"toolcall.waiting_input": "Waiting for your input",
|
|
@@ -1834,6 +1844,8 @@ const dictionaries = {
|
|
|
1834
1844
|
"export.session_title": "# Scream Session Export",
|
|
1835
1845
|
"bgtask.agent_task": "Agent task",
|
|
1836
1846
|
"bgtask.bash_task": "Bash task",
|
|
1847
|
+
"bash.background_completed": "Background task {id} completed: {command}",
|
|
1848
|
+
"bash.background_failed": "Background task {id} failed (exit {exitCode}): {command}",
|
|
1837
1849
|
"bgtask.started_bg": "{subject} started in background",
|
|
1838
1850
|
"bgtask.awaiting_approval": "{subject} awaiting approval",
|
|
1839
1851
|
"bgtask.completed_bg": "{subject} completed in background",
|
|
@@ -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 { t as TextInputDialogComponent } from "./text-input-dialog-
|
|
6
|
+
import { t as TextInputDialogComponent } from "./text-input-dialog-BdUmo73M.mjs";
|
|
7
7
|
export { TextInputDialogComponent };
|