scream-code 0.12.1 → 0.12.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.
|
@@ -54,7 +54,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
54
54
|
import { Command, Option } from "commander";
|
|
55
55
|
import { createInterface } from "node:readline/promises";
|
|
56
56
|
import chalk, { chalkStderr } from "chalk";
|
|
57
|
-
import { CombinedAutocompleteProvider, Container, Editor, Image, Input, Key, Markdown, ProcessTerminal, Spacer, TUI, Text, decodeKittyPrintable, deleteAllKittyImages, fuzzyFilter, fuzzyMatch, getCapabilities, getImageDimensions, isKeyRelease, matchesKey, setTightMode, sliceByColumn, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@liutod-scream/pi-tui";
|
|
57
|
+
import { CombinedAutocompleteProvider, Container, Editor, FlexSpacer, Image, Input, Key, Markdown, ProcessTerminal, Spacer, TUI, Text, decodeKittyPrintable, deleteAllKittyImages, fuzzyFilter, fuzzyMatch, getCapabilities, getImageDimensions, isKeyRelease, matchesKey, setTightMode, sliceByColumn, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@liutod-scream/pi-tui";
|
|
58
58
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
59
59
|
import { diffWords } from "diff";
|
|
60
60
|
import { gt, valid } from "semver";
|
|
@@ -120898,7 +120898,7 @@ function optionalBuildString(value) {
|
|
|
120898
120898
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
120899
120899
|
}
|
|
120900
120900
|
const SCREAM_BUILD_INFO = {
|
|
120901
|
-
version: optionalBuildString("0.12.
|
|
120901
|
+
version: optionalBuildString("0.12.2"),
|
|
120902
120902
|
channel: optionalBuildString(""),
|
|
120903
120903
|
commit: optionalBuildString(""),
|
|
120904
120904
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -124105,7 +124105,7 @@ function formatTokenCount$1(n) {
|
|
|
124105
124105
|
return String(Math.round(n));
|
|
124106
124106
|
}
|
|
124107
124107
|
/**
|
|
124108
|
-
* Build a
|
|
124108
|
+
* Build a `███░░░░░░░` style bar. Returns a plain-ASCII string with
|
|
124109
124109
|
* `filled`/`empty` glyphs — colouring is the caller's responsibility.
|
|
124110
124110
|
*/
|
|
124111
124111
|
function renderProgressBar(ratio, width = 20, filled = "█", empty = "░") {
|
|
@@ -124153,20 +124153,18 @@ function currencySymbol(currency) {
|
|
|
124153
124153
|
return `${currency} `;
|
|
124154
124154
|
}
|
|
124155
124155
|
/**
|
|
124156
|
-
* Water-level progress bar for context usage:
|
|
124156
|
+
* Water-level progress bar for context usage: `█████▓▒░░░` (10 cells).
|
|
124157
124157
|
* Used cells read as water — solid depth (█) with a foam transition (▓▒)
|
|
124158
124158
|
* hugging the water line; unused cells read as air (░). Cell count is
|
|
124159
124159
|
* rounded from the clamped ratio, so 0% is all-air and >=100% is all-water;
|
|
124160
|
-
* NaN/undefined coerce through safeUsageRatio first.
|
|
124161
|
-
* part of the returned string so a trailing background cell is never
|
|
124162
|
-
* swallowed by the terminal.
|
|
124160
|
+
* NaN/undefined coerce through safeUsageRatio first.
|
|
124163
124161
|
*/
|
|
124164
124162
|
function formatContextBar(usage, width = CONTEXT_BAR_WIDTH) {
|
|
124165
124163
|
const clamped = Math.min(1, Math.max(0, safeUsageRatio(usage)));
|
|
124166
124164
|
const filled = Math.round(clamped * width);
|
|
124167
124165
|
const foam = Math.min(2, filled);
|
|
124168
124166
|
const deep = Math.max(0, filled - foam);
|
|
124169
|
-
return
|
|
124167
|
+
return `${CONTEXT_BAR_DEEP.repeat(deep) + CONTEXT_BAR_FOAM.slice(0, foam)}${CONTEXT_BAR_AIR.repeat(width - filled)}`;
|
|
124170
124168
|
}
|
|
124171
124169
|
function formatContextStatus(usage, tokens, maxTokens, barWidth = CONTEXT_BAR_WIDTH) {
|
|
124172
124170
|
const pct = `${(safeUsage(usage) * 100).toFixed(1)}%`;
|
|
@@ -140983,6 +140981,7 @@ var LifecycleController = class LifecycleController {
|
|
|
140983
140981
|
ui.addChild(this.host.state.queueContainer);
|
|
140984
140982
|
ui.addChild(this.host.state.errorBannerContainer);
|
|
140985
140983
|
ui.addChild(this.host.state.planModeBannerContainer);
|
|
140984
|
+
ui.addChild(new FlexSpacer());
|
|
140986
140985
|
ui.addChild(this.host.state.editorContainer);
|
|
140987
140986
|
}
|
|
140988
140987
|
mountFooter() {
|
|
@@ -143359,6 +143358,24 @@ function adaptQuestionAnswers(event, response) {
|
|
|
143359
143358
|
//#endregion
|
|
143360
143359
|
//#region src/tui/managers/session-manager.ts
|
|
143361
143360
|
/**
|
|
143361
|
+
* How recently a session must have been touched for the empty-session pruner
|
|
143362
|
+
* to leave it alone. Guards against sweeping a fresh empty session that
|
|
143363
|
+
* another terminal is about to use.
|
|
143364
|
+
*/
|
|
143365
|
+
const PRUNE_EMPTY_SESSION_GRACE_MS = 300 * 1e3;
|
|
143366
|
+
/**
|
|
143367
|
+
* A session is prunable when it never received a user prompt and never got a
|
|
143368
|
+
* title (auto-generated or custom) — i.e. an empty shell left behind by a
|
|
143369
|
+
* one-off startup. Archived sessions and sessions touched within the grace
|
|
143370
|
+
* window are kept.
|
|
143371
|
+
*/
|
|
143372
|
+
function isPrunableEmptySession(summary, now, graceMs = PRUNE_EMPTY_SESSION_GRACE_MS) {
|
|
143373
|
+
if (summary.archived) return false;
|
|
143374
|
+
if (summary.lastPrompt !== void 0) return false;
|
|
143375
|
+
if (summary.title) return false;
|
|
143376
|
+
return now - summary.updatedAt > graceMs;
|
|
143377
|
+
}
|
|
143378
|
+
/**
|
|
143362
143379
|
* Encapsulates all session lifecycle operations:
|
|
143363
143380
|
* create / resume / switch / close / sync state / reset runtime.
|
|
143364
143381
|
*/
|
|
@@ -143412,12 +143429,34 @@ var SessionManager$1 = class {
|
|
|
143412
143429
|
await this.syncRuntimeState(session);
|
|
143413
143430
|
if (startup.wolfpack && !isResumeStartup) await session.setWolfpackMode(true);
|
|
143414
143431
|
this.host.state.startupState = "ready";
|
|
143432
|
+
await this.pruneEmptySessions(workDir, session.id);
|
|
143415
143433
|
this.host.sessionEventHandler.startSubscription();
|
|
143416
143434
|
return {
|
|
143417
143435
|
session,
|
|
143418
143436
|
shouldReplay: shouldReplayHistory
|
|
143419
143437
|
};
|
|
143420
143438
|
}
|
|
143439
|
+
/**
|
|
143440
|
+
* Deletes sessions in this workdir that never received a user prompt and
|
|
143441
|
+
* were never renamed — repeated startups otherwise leave a growing pile of
|
|
143442
|
+
* one-off empty session shells. The session about to be used is skipped, as
|
|
143443
|
+
* are archived sessions, any session that produced a prompt or a title, and
|
|
143444
|
+
* any session touched within the grace window (protects a fresh empty
|
|
143445
|
+
* session being used from another terminal). Best-effort: cleanup failures
|
|
143446
|
+
* never block startup.
|
|
143447
|
+
*/
|
|
143448
|
+
async pruneEmptySessions(workDir, currentSessionId) {
|
|
143449
|
+
try {
|
|
143450
|
+
const now = Date.now();
|
|
143451
|
+
const summaries = await this.host.harness.listSessions({ workDir });
|
|
143452
|
+
for (const summary of summaries) {
|
|
143453
|
+
if (summary.id === currentSessionId) continue;
|
|
143454
|
+
if (isPrunableEmptySession(summary, now)) await this.host.harness.deleteSession(summary.id);
|
|
143455
|
+
}
|
|
143456
|
+
} catch (error) {
|
|
143457
|
+
this.host.showStatus(`Session cleanup skipped: ${String(error)}`);
|
|
143458
|
+
}
|
|
143459
|
+
}
|
|
143421
143460
|
async setSession(session) {
|
|
143422
143461
|
await this.unloadCurrentSession("switching session")?.close({ extractMemories: false });
|
|
143423
143462
|
this.host.session = session;
|
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-1A238nr4.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.12.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "A terminal-native AI agent for builders",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "ScreamCli",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"smoke": "node dist/main.mjs --version"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
|
-
"@liutod-scream/pi-tui": "^0.80.
|
|
62
|
+
"@liutod-scream/pi-tui": "^0.80.39",
|
|
63
63
|
"@mariozechner/clipboard": "^0.3.2",
|
|
64
64
|
"chalk": "^5.4.1",
|
|
65
65
|
"cli-highlight": "^2.1.11",
|