scream-code 0.15.2 → 0.15.3
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/dist/{app-6Hcxs2tP.mjs → app-Bqc3MVGh.mjs} +56 -28
- package/dist/{dispatch-Dur5jHVw.mjs → dispatch-CweYoXh3.mjs} +1 -1
- package/dist/{dispatch-B_ViYZer.mjs → dispatch-DGeogib-.mjs} +131 -38
- package/dist/main.mjs +1 -1
- package/dist/public/assets/{index-BfVIY6UW.css → index-BJaeSGtC.css} +1 -1
- package/dist/public/assets/index-DDVdau1l.js +93 -0
- package/dist/public/assets/index-DDVdau1l.js.map +1 -0
- package/dist/public/index.html +2 -2
- package/package.json +2 -2
- package/dist/public/assets/index-B9I4PIWR.js +0 -93
- package/dist/public/assets/index-B9I4PIWR.js.map +0 -1
|
@@ -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 { $t as isTodoItemShape, A as renderDiffLinesClustered, An as getInputHistoryFile, At as ENABLE_TERMINAL_FOCUS_REPORTING, B as BackgroundAgentStatusComponent, Bn as ScreamHarness, Bt as TERMINAL_THEME_LIGHT, Cn as PULSE_WAVE_FRAMES, Ct as createThemeStyles, D as toggleEmptySessionHint, Dn as saveTuiConfig, Dt as parseOsc11BackgroundTheme, E as isTurnElapsedEnabled, En as loadTuiConfig, Et as detectTerminalTheme, F as estimateTokens, Fn as CLI_USER_AGENT_PRODUCT, Ft as OSC11_RESPONSE_PREFIX_NO_ESC, G as getBreathingFrame, Gn as log, H as AgentGroupComponent, Hn as resolveScreamHome, Ht as isStreaming, I as getSharedSpeedTracker, In as PRODUCT_NAME, It as QUERY_TERMINAL_THEME, J as refineGoal, Jn as isOrphanedToolCallError, Jt as printableChar, K as resetBreathingClock, Kn as resolveGlobalLogPath, L as SkillActivationComponent, Ln as DEFAULT_CATALOG_URL, Lt as TERMINAL_FOCUS_IN, M as langFromPath, Mn as detectInstallSource, Mt as OSC11_QUERY, N as CachedContainer, Nn as CLI_COMMAND_NAME, Nt as OSC11_RESPONSE, O as ToolCallComponent, On as detectShellEnvironment, Ot as DISABLE_TERMINAL_FOCUS_REPORTING, P as ThinkingComponent, Pn as CLI_UI_MODE, Pt as OSC11_RESPONSE_PREFIX, Qt as formatErrorMessage, R as ReadGroupComponent, Rn as fetchCatalog, Rt as TERMINAL_FOCUS_OUT, S as getDaemonInstructions, Sn as PIXEL_PULSE_FRAMES, St as createMarkdownTheme, T as isEmptySessionHintDismissed, Tn as TuiLikePreferencesSchema, Tt as getColorPalette, U as WelcomeComponent, Un as MemoryMemoStore, Ut as FooterComponent, V as AssistantMessageComponent, Vt as isBusy, W as BREATHE_CYCLE_MS, Wn as flushDiagnosticLogs, Xn as SCREAM_ERROR_INFO, Xt as appendStreamingArgsPreview, Yn as ErrorCodes, Yt as STATUS_BULLET, Zt as argsRecord, _ as refreshUpdateCache, _n as isExperimentalFlagEnabled, _t as clearInfoPanelState, an as EMPTY_SESSION_HINT_URL, b as readJsonlFile, bn as isEmbeddingModelCached, bt as resolveThemeSync, c as hasDispose, cn as SESSION_TIPS, ct as handlePlanCommand, d as formatMemoryMemoForInjection, dn as getCtrlDHint, en as parseStreamingArgs, et as toTerminalHyperlink, fn as getLlmNotSetMessage, g as selectUpdateTarget, gn as sortSlashCommands, gt as supportsBalance, hn as BUILTIN_SLASH_COMMANDS, ht as refreshProviderBalance, i as buildRoleAdditionalText, in as CHARS_PER_TOKEN, j as highlightLines, jn as getLogDir, jt as ENABLE_TERMINAL_THEME_REPORTING, k as renderDiffLines, kn as getDataDir, kt as DISABLE_TERMINAL_THEME_REPORTING, l as isPlanExpandable, ln as TIP_ROTATION_INTERVAL_MS, mn as buildSkillSlashCommands, n as clearEvalPanelState, nn as stringValue, nt as getModelCycleLevel, on as EXIT_CONFIRM_WINDOW_MS, ot as handleFusionPlanCommand, pn as getNoActiveSessionMessage, q as clearGoalState, qn as isScreamError, r as openUrl, rn as truncateErrorMessage, s as disposeChildren, sn as MAIN_AGENT_ID, t as dispatchInput, tn as serializeToolResultOutput, tt as changeThinkingLevel, u as MoonLoader, un as getCtrlCHint, v as readUpdateCache, vn as setExperimentalFlags, w as UserMessageComponent, wn as TuiConfigParseError, wt as contrastTextHex, xn as startManualEmbeddingDownload, xt as createEditorTheme, y as appendJsonlLine, yn as getKnowledgeStore, z as parseReadGroupOutput, zn as saveCatalogCache, zt as TERMINAL_THEME_DARK } from "./dispatch-
|
|
7
|
+
import { $t as isTodoItemShape, A as renderDiffLinesClustered, An as getInputHistoryFile, At as ENABLE_TERMINAL_FOCUS_REPORTING, B as BackgroundAgentStatusComponent, Bn as ScreamHarness, Bt as TERMINAL_THEME_LIGHT, Cn as PULSE_WAVE_FRAMES, Ct as createThemeStyles, D as toggleEmptySessionHint, Dn as saveTuiConfig, Dt as parseOsc11BackgroundTheme, E as isTurnElapsedEnabled, En as loadTuiConfig, Et as detectTerminalTheme, F as estimateTokens, Fn as CLI_USER_AGENT_PRODUCT, Ft as OSC11_RESPONSE_PREFIX_NO_ESC, G as getBreathingFrame, Gn as log, H as AgentGroupComponent, Hn as resolveScreamHome, Ht as isStreaming, I as getSharedSpeedTracker, In as PRODUCT_NAME, It as QUERY_TERMINAL_THEME, J as refineGoal, Jn as isOrphanedToolCallError, Jt as printableChar, K as resetBreathingClock, Kn as resolveGlobalLogPath, L as SkillActivationComponent, Ln as DEFAULT_CATALOG_URL, Lt as TERMINAL_FOCUS_IN, M as langFromPath, Mn as detectInstallSource, Mt as OSC11_QUERY, N as CachedContainer, Nn as CLI_COMMAND_NAME, Nt as OSC11_RESPONSE, O as ToolCallComponent, On as detectShellEnvironment, Ot as DISABLE_TERMINAL_FOCUS_REPORTING, P as ThinkingComponent, Pn as CLI_UI_MODE, Pt as OSC11_RESPONSE_PREFIX, Qt as formatErrorMessage, R as ReadGroupComponent, Rn as fetchCatalog, Rt as TERMINAL_FOCUS_OUT, S as getDaemonInstructions, Sn as PIXEL_PULSE_FRAMES, St as createMarkdownTheme, T as isEmptySessionHintDismissed, Tn as TuiLikePreferencesSchema, Tt as getColorPalette, U as WelcomeComponent, Un as MemoryMemoStore, Ut as FooterComponent, V as AssistantMessageComponent, Vt as isBusy, W as BREATHE_CYCLE_MS, Wn as flushDiagnosticLogs, Xn as SCREAM_ERROR_INFO, Xt as appendStreamingArgsPreview, Yn as ErrorCodes, Yt as STATUS_BULLET, Zt as argsRecord, _ as refreshUpdateCache, _n as isExperimentalFlagEnabled, _t as clearInfoPanelState, an as EMPTY_SESSION_HINT_URL, b as readJsonlFile, bn as isEmbeddingModelCached, bt as resolveThemeSync, c as hasDispose, cn as SESSION_TIPS, ct as handlePlanCommand, d as formatMemoryMemoForInjection, dn as getCtrlDHint, en as parseStreamingArgs, et as toTerminalHyperlink, fn as getLlmNotSetMessage, g as selectUpdateTarget, gn as sortSlashCommands, gt as supportsBalance, hn as BUILTIN_SLASH_COMMANDS, ht as refreshProviderBalance, i as buildRoleAdditionalText, in as CHARS_PER_TOKEN, j as highlightLines, jn as getLogDir, jt as ENABLE_TERMINAL_THEME_REPORTING, k as renderDiffLines, kn as getDataDir, kt as DISABLE_TERMINAL_THEME_REPORTING, l as isPlanExpandable, ln as TIP_ROTATION_INTERVAL_MS, mn as buildSkillSlashCommands, n as clearEvalPanelState, nn as stringValue, nt as getModelCycleLevel, on as EXIT_CONFIRM_WINDOW_MS, ot as handleFusionPlanCommand, pn as getNoActiveSessionMessage, q as clearGoalState, qn as isScreamError, r as openUrl, rn as truncateErrorMessage, s as disposeChildren, sn as MAIN_AGENT_ID, t as dispatchInput, tn as serializeToolResultOutput, tt as changeThinkingLevel, u as MoonLoader, un as getCtrlCHint, v as readUpdateCache, vn as setExperimentalFlags, w as UserMessageComponent, wn as TuiConfigParseError, wt as contrastTextHex, xn as startManualEmbeddingDownload, xt as createEditorTheme, y as appendJsonlLine, yn as getKnowledgeStore, z as parseReadGroupOutput, zn as saveCatalogCache, zt as TERMINAL_THEME_DARK } from "./dispatch-DGeogib-.mjs";
|
|
8
8
|
import { a as setLocale, o as t } from "./text-input-dialog-BUXAKycx.mjs";
|
|
9
9
|
import { createRequire } from "node:module";
|
|
10
10
|
import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
@@ -32,7 +32,7 @@ function optionalBuildString(value) {
|
|
|
32
32
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
33
33
|
}
|
|
34
34
|
const SCREAM_BUILD_INFO = {
|
|
35
|
-
version: optionalBuildString("0.15.
|
|
35
|
+
version: optionalBuildString("0.15.3"),
|
|
36
36
|
channel: optionalBuildString(""),
|
|
37
37
|
commit: optionalBuildString(""),
|
|
38
38
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -6553,27 +6553,34 @@ function installTerminalThemeTracking(state, onTheme) {
|
|
|
6553
6553
|
}
|
|
6554
6554
|
//#endregion
|
|
6555
6555
|
//#region src/tui/components/chrome/pulse-wave-loader.ts
|
|
6556
|
-
|
|
6557
|
-
|
|
6556
|
+
/** Leading/trailing glyph: U+2588 (Block Elements — guaranteed single-column
|
|
6557
|
+
* width). The remaining stage cells render muted middle dots (U+00B7). */
|
|
6558
|
+
const LEADING_BOX = "■";
|
|
6558
6559
|
/**
|
|
6559
|
-
*
|
|
6560
|
+
* 8-box flowing pulse-wave loading indicator.
|
|
6560
6561
|
*
|
|
6561
|
-
*
|
|
6562
|
-
*
|
|
6562
|
+
* A leading box (full primary colour) sweeps across an 8-cell stage, trailed
|
|
6563
|
+
* by a dim box, over a row of muted middle dots:
|
|
6564
|
+
* ■ 淡 ■ · · · · · · → ■ ■ 淡 ■ · · · · → … → (bounce back)
|
|
6565
|
+
* (淡 shown here only to mark the trailing box; it renders as primary+dim.)
|
|
6563
6566
|
*
|
|
6564
|
-
*
|
|
6565
|
-
*
|
|
6566
|
-
*
|
|
6567
|
-
*
|
|
6567
|
+
* 14-frame ping-pong loop @ 80 ms — the leading edge never teleports, it
|
|
6568
|
+
* walks cell by cell.
|
|
6569
|
+
*
|
|
6570
|
+
* All glyphs are width-safe in terminal fonts (U+2588 Block Elements and
|
|
6571
|
+
* U+00B7 Latin-1) — the earlier ■/⬝ mix reflowed the whole line on every
|
|
6572
|
+
* frame because U+2B1D is not single-column guaranteed.
|
|
6568
6573
|
*
|
|
6569
6574
|
* The component auto-starts on construction. Call `stop()` to tear
|
|
6570
|
-
* down the
|
|
6575
|
+
* down the timer chain.
|
|
6571
6576
|
*/
|
|
6572
6577
|
var PulseWaveLoader = class extends Text {
|
|
6573
6578
|
currentFrame = 0;
|
|
6574
6579
|
intervalId = null;
|
|
6575
6580
|
ui;
|
|
6576
6581
|
colorHex;
|
|
6582
|
+
/** Wall-clock time of the last frame advance, for drift-free scheduling. */
|
|
6583
|
+
lastTickAt = 0;
|
|
6577
6584
|
/** Raw frame text without Text's full-width render padding, exposed so
|
|
6578
6585
|
* callers can compose the wave inline with trailing content (e.g. the
|
|
6579
6586
|
* reconnect label in the status bar). */
|
|
@@ -6589,39 +6596,60 @@ var PulseWaveLoader = class extends Text {
|
|
|
6589
6596
|
this.start();
|
|
6590
6597
|
}
|
|
6591
6598
|
start() {
|
|
6599
|
+
this.lastTickAt = performance.now();
|
|
6592
6600
|
this.updateDisplay();
|
|
6593
|
-
this.
|
|
6594
|
-
this.currentFrame = (this.currentFrame + 1) % PULSE_WAVE_FRAMES.length;
|
|
6595
|
-
this.updateDisplay();
|
|
6596
|
-
}, 120);
|
|
6601
|
+
this.scheduleTick(80, 80);
|
|
6597
6602
|
}
|
|
6598
6603
|
stop() {
|
|
6599
6604
|
if (this.intervalId) {
|
|
6600
|
-
|
|
6605
|
+
clearTimeout(this.intervalId);
|
|
6601
6606
|
this.intervalId = null;
|
|
6602
6607
|
}
|
|
6603
6608
|
}
|
|
6609
|
+
dispose() {
|
|
6610
|
+
this.stop();
|
|
6611
|
+
}
|
|
6612
|
+
/**
|
|
6613
|
+
* setTimeout self-rescheduling chain with drift-free frame advancement and
|
|
6614
|
+
* paint-cost backpressure (same pattern as the pi-tui Loader): a slow tick
|
|
6615
|
+
* defers the next one by `max(0, interval - cost, cost × 9)` instead of
|
|
6616
|
+
* stacking intervals, keeping the wave ≤ ~10% CPU under slow writes.
|
|
6617
|
+
*/
|
|
6618
|
+
scheduleTick(intervalMs, delayMs) {
|
|
6619
|
+
const timer = setTimeout(() => {
|
|
6620
|
+
if (this.intervalId !== timer) return;
|
|
6621
|
+
const startedAt = performance.now();
|
|
6622
|
+
const elapsed = startedAt - this.lastTickAt;
|
|
6623
|
+
if (elapsed >= intervalMs) {
|
|
6624
|
+
const steps = Math.floor(elapsed / intervalMs);
|
|
6625
|
+
this.currentFrame = (this.currentFrame + steps) % PULSE_WAVE_FRAMES.length;
|
|
6626
|
+
this.lastTickAt += steps * intervalMs;
|
|
6627
|
+
this.updateDisplay();
|
|
6628
|
+
}
|
|
6629
|
+
const frameCostMs = performance.now() - startedAt;
|
|
6630
|
+
if (this.intervalId !== timer) return;
|
|
6631
|
+
const cadenceDelayMs = Math.max(0, intervalMs - frameCostMs);
|
|
6632
|
+
const backpressureDelayMs = frameCostMs * 9;
|
|
6633
|
+
this.scheduleTick(intervalMs, Math.max(cadenceDelayMs, backpressureDelayMs));
|
|
6634
|
+
}, delayMs);
|
|
6635
|
+
this.intervalId = timer;
|
|
6636
|
+
}
|
|
6604
6637
|
setColorHex(colorHex) {
|
|
6605
6638
|
this.colorHex = colorHex;
|
|
6606
6639
|
this.updateDisplay();
|
|
6607
6640
|
}
|
|
6608
6641
|
updateDisplay() {
|
|
6609
6642
|
const step = PULSE_WAVE_FRAMES[this.currentFrame] ?? PULSE_WAVE_FRAMES[0];
|
|
6610
|
-
const cells =
|
|
6611
|
-
|
|
6612
|
-
1,
|
|
6613
|
-
2
|
|
6614
|
-
].map((idx) => this.renderCell(idx, step.active, step.forward));
|
|
6615
|
-
this.frameText = cells.join(" ");
|
|
6643
|
+
const cells = Array.from({ length: 8 }, (_, idx) => this.renderCell(idx, step.active, step.forward));
|
|
6644
|
+
this.frameText = cells.join("");
|
|
6616
6645
|
this.setText(this.frameText);
|
|
6617
6646
|
this.ui.requestRender();
|
|
6618
6647
|
}
|
|
6619
6648
|
renderCell(index, active, forward) {
|
|
6620
6649
|
const distance = forward ? active - index : index - active;
|
|
6621
|
-
|
|
6622
|
-
if (distance ===
|
|
6623
|
-
|
|
6624
|
-
return chalk.dim(glyph);
|
|
6650
|
+
if (distance === 0) return chalk.hex(this.colorHex)(LEADING_BOX);
|
|
6651
|
+
if (distance === 1) return chalk.hex(this.colorHex).dim(LEADING_BOX);
|
|
6652
|
+
return chalk.dim("·");
|
|
6625
6653
|
}
|
|
6626
6654
|
};
|
|
6627
6655
|
//#endregion
|
|
@@ -12397,7 +12425,7 @@ var ScreamTUI = class {
|
|
|
12397
12425
|
const card = new OnboardingCardComponent({
|
|
12398
12426
|
colors: this.state.theme.colors,
|
|
12399
12427
|
onConfigure: () => {
|
|
12400
|
-
import("./dispatch-
|
|
12428
|
+
import("./dispatch-CweYoXh3.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
|
|
12401
12429
|
this.restoreEditor();
|
|
12402
12430
|
onDone?.();
|
|
12403
12431
|
});
|
|
@@ -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 { Kt as handleConnectCommand } from "./dispatch-
|
|
6
|
+
import { Kt as handleConnectCommand } from "./dispatch-DGeogib-.mjs";
|
|
7
7
|
export { handleConnectCommand };
|
|
@@ -47632,9 +47632,41 @@ function estimateTokensForMessage(message) {
|
|
|
47632
47632
|
messageTokenCache.set(message, total);
|
|
47633
47633
|
return total;
|
|
47634
47634
|
}
|
|
47635
|
+
/**
|
|
47636
|
+
* Media parts carry no width/height metadata, and providers differ on how they
|
|
47637
|
+
* tokenize media (image token counts range from a few hundred to ~1600 for a
|
|
47638
|
+
* single image depending on provider and resolution). There is no cross-
|
|
47639
|
+
* provider formula, so these estimates are deliberately conservative — for
|
|
47640
|
+
* watermark detection an OVERestimate only compacts slightly earlier
|
|
47641
|
+
* (harmless), whereas counting media as 0 systematically UNDERESTIMATED the
|
|
47642
|
+
* watermark and delayed compaction on media-heavy sessions.
|
|
47643
|
+
*
|
|
47644
|
+
* These estimates are consumed only by watermark detection and micro-compaction
|
|
47645
|
+
* recycling decisions — the real usage reported by the provider re-anchors the
|
|
47646
|
+
* context token count at each step end, so billing/usage accounting is
|
|
47647
|
+
* unaffected.
|
|
47648
|
+
*/
|
|
47649
|
+
const IMAGE_BASE_TOKENS = 1600;
|
|
47650
|
+
const IMAGE_MAX_TOKENS = 8e3;
|
|
47651
|
+
/** data-URI payloads above this many bytes are treated as high-resolution/long captures. */
|
|
47652
|
+
const IMAGE_LARGE_PAYLOAD_BYTES = 512e3;
|
|
47653
|
+
const AUDIO_TOKENS = 2e3;
|
|
47654
|
+
const VIDEO_TOKENS = 5e3;
|
|
47655
|
+
/** Long screenshots (large data URIs) carry more visual content than a single
|
|
47656
|
+
* bounded-resolution image; grow the estimate linearly and cap it. */
|
|
47657
|
+
function estimateDataUriTokens(url, baseTokens, maxTokens) {
|
|
47658
|
+
const start = url.indexOf("base64,");
|
|
47659
|
+
if (start < 0) return baseTokens;
|
|
47660
|
+
const bytes = Math.floor((url.length - start - 7) * 3 / 4);
|
|
47661
|
+
if (bytes <= IMAGE_LARGE_PAYLOAD_BYTES) return baseTokens;
|
|
47662
|
+
return Math.min(maxTokens, baseTokens + Math.floor((bytes - IMAGE_LARGE_PAYLOAD_BYTES) / 1e3));
|
|
47663
|
+
}
|
|
47635
47664
|
function estimateTokensForContentPart(part) {
|
|
47636
47665
|
if (part.type === "text") return estimateTokens$1(part.text);
|
|
47637
47666
|
else if (part.type === "think") return estimateTokens$1(part.think);
|
|
47667
|
+
else if (part.type === "image_url") return estimateDataUriTokens(part.imageUrl.url, IMAGE_BASE_TOKENS, IMAGE_MAX_TOKENS);
|
|
47668
|
+
else if (part.type === "audio_url") return AUDIO_TOKENS;
|
|
47669
|
+
else if (part.type === "video_url") return VIDEO_TOKENS;
|
|
47638
47670
|
return 0;
|
|
47639
47671
|
}
|
|
47640
47672
|
//#endregion
|
|
@@ -78968,7 +79000,11 @@ var FullCompaction = class {
|
|
|
78968
79000
|
this.agent.context.applyCompaction(result);
|
|
78969
79001
|
this.lastCompactionFiles = fileLists;
|
|
78970
79002
|
this.lowWaterMark = Math.floor(this.effectiveTokenCount * 1.1);
|
|
78971
|
-
|
|
79003
|
+
try {
|
|
79004
|
+
await this.extractAndStoreMemos(processedSummary, messagesToCompactForOps);
|
|
79005
|
+
} catch (error) {
|
|
79006
|
+
this.agent.log.warn("Memory memo extraction failed (compaction itself succeeded)", { error });
|
|
79007
|
+
}
|
|
78972
79008
|
this.triggerPostCompactHook(data, result);
|
|
78973
79009
|
this.detectSkillCandidates(skillCandidateSummary);
|
|
78974
79010
|
this.consecutiveCompactionFailures = 0;
|
|
@@ -79431,7 +79467,7 @@ function findSupersededPaths(messages, cutoff) {
|
|
|
79431
79467
|
/**
|
|
79432
79468
|
* Lightweight compaction that truncates old tool results without an LLM call.
|
|
79433
79469
|
*
|
|
79434
|
-
* When the context window is filling up (>=
|
|
79470
|
+
* When the context window is filling up (>= 30% by default), old tool result
|
|
79435
79471
|
* messages are replaced with a short placeholder. This frees up tokens for the
|
|
79436
79472
|
* model without the cost and latency of a full compaction.
|
|
79437
79473
|
*
|
|
@@ -125641,24 +125677,15 @@ const PIXEL_PULSE_FRAMES = [
|
|
|
125641
125677
|
"▒",
|
|
125642
125678
|
"▓"
|
|
125643
125679
|
];
|
|
125644
|
-
const
|
|
125645
|
-
|
|
125646
|
-
|
|
125647
|
-
|
|
125648
|
-
|
|
125649
|
-
|
|
125650
|
-
|
|
125651
|
-
|
|
125652
|
-
|
|
125653
|
-
{
|
|
125654
|
-
active: 2,
|
|
125655
|
-
forward: true
|
|
125656
|
-
},
|
|
125657
|
-
{
|
|
125658
|
-
active: 1,
|
|
125659
|
-
forward: false
|
|
125660
|
-
}
|
|
125661
|
-
];
|
|
125680
|
+
const forwardFrames = Array.from({ length: 8 }, (_, active) => ({
|
|
125681
|
+
active,
|
|
125682
|
+
forward: true
|
|
125683
|
+
}));
|
|
125684
|
+
const backwardFrames = Array.from({ length: 6 }, (_, i) => ({
|
|
125685
|
+
active: 6 - i,
|
|
125686
|
+
forward: false
|
|
125687
|
+
}));
|
|
125688
|
+
const PULSE_WAVE_FRAMES = [...forwardFrames, ...backwardFrames];
|
|
125662
125689
|
//#endregion
|
|
125663
125690
|
//#region src/tui/commands/knowledge-store.ts
|
|
125664
125691
|
let knowledgeStoreInstance;
|
|
@@ -129444,13 +129471,22 @@ var FooterComponent = class {
|
|
|
129444
129471
|
this.#stopStatusTimer();
|
|
129445
129472
|
if (phase === "idle" && !goalActive) return;
|
|
129446
129473
|
const intervalMs = 1e3 / 30;
|
|
129447
|
-
this
|
|
129474
|
+
this.#scheduleStatusTick(intervalMs, intervalMs);
|
|
129475
|
+
}
|
|
129476
|
+
#scheduleStatusTick(intervalMs, delayMs) {
|
|
129477
|
+
const timer = setTimeout(() => {
|
|
129478
|
+
if (this.statusTimer !== timer) return;
|
|
129479
|
+
const startedAt = performance.now();
|
|
129448
129480
|
this.ui.requestRender();
|
|
129449
|
-
|
|
129481
|
+
const tickCostMs = performance.now() - startedAt;
|
|
129482
|
+
if (this.statusTimer !== timer) return;
|
|
129483
|
+
this.#scheduleStatusTick(intervalMs, Math.max(0, intervalMs - tickCostMs));
|
|
129484
|
+
}, delayMs);
|
|
129485
|
+
this.statusTimer = timer;
|
|
129450
129486
|
}
|
|
129451
129487
|
#stopStatusTimer() {
|
|
129452
129488
|
if (!this.statusTimer) return;
|
|
129453
|
-
|
|
129489
|
+
clearTimeout(this.statusTimer);
|
|
129454
129490
|
this.statusTimer = null;
|
|
129455
129491
|
}
|
|
129456
129492
|
render(width) {
|
|
@@ -133126,7 +133162,8 @@ var ThinkingComponent = class {
|
|
|
133126
133162
|
expanded = false;
|
|
133127
133163
|
ui;
|
|
133128
133164
|
spinnerFrame = 0;
|
|
133129
|
-
|
|
133165
|
+
spinnerTimer;
|
|
133166
|
+
lastSpinnerTickAt = 0;
|
|
133130
133167
|
textComponent;
|
|
133131
133168
|
cachedWidth;
|
|
133132
133169
|
cachedLines;
|
|
@@ -133210,17 +133247,41 @@ var ThinkingComponent = class {
|
|
|
133210
133247
|
}
|
|
133211
133248
|
return truncated;
|
|
133212
133249
|
}
|
|
133250
|
+
/**
|
|
133251
|
+
* setTimeout self-rescheduling chain with drift-free frame advancement and
|
|
133252
|
+
* paint-cost backpressure (same pattern as the pi-tui Loader): a slow tick
|
|
133253
|
+
* defers the next one instead of stacking intervals, keeping the live
|
|
133254
|
+
* thinking indicator ≤ ~10% CPU even under slow terminal writes.
|
|
133255
|
+
*/
|
|
133256
|
+
scheduleSpinnerTick(delayMs) {
|
|
133257
|
+
if (this.ui === void 0) return;
|
|
133258
|
+
const timer = setTimeout(() => {
|
|
133259
|
+
if (this.spinnerTimer !== timer) return;
|
|
133260
|
+
const startedAt = performance.now();
|
|
133261
|
+
const elapsed = startedAt - this.lastSpinnerTickAt;
|
|
133262
|
+
if (elapsed >= 80) {
|
|
133263
|
+
const steps = Math.floor(elapsed / 80);
|
|
133264
|
+
this.spinnerFrame = (this.spinnerFrame + steps) % BRAILLE_SPINNER_FRAMES.length;
|
|
133265
|
+
this.lastSpinnerTickAt += steps * 80;
|
|
133266
|
+
this.ui?.requestRender();
|
|
133267
|
+
}
|
|
133268
|
+
const frameCostMs = performance.now() - startedAt;
|
|
133269
|
+
if (this.spinnerTimer !== timer) return;
|
|
133270
|
+
const cadenceDelayMs = Math.max(0, 80 - frameCostMs);
|
|
133271
|
+
const backpressureDelayMs = frameCostMs * 9;
|
|
133272
|
+
this.scheduleSpinnerTick(Math.max(cadenceDelayMs, backpressureDelayMs));
|
|
133273
|
+
}, delayMs);
|
|
133274
|
+
this.spinnerTimer = timer;
|
|
133275
|
+
}
|
|
133213
133276
|
startSpinner() {
|
|
133214
|
-
if (this.ui === void 0 || this.
|
|
133215
|
-
this.
|
|
133216
|
-
|
|
133217
|
-
this.ui?.requestRender();
|
|
133218
|
-
}, 80);
|
|
133277
|
+
if (this.ui === void 0 || this.spinnerTimer !== void 0) return;
|
|
133278
|
+
this.lastSpinnerTickAt = performance.now();
|
|
133279
|
+
this.scheduleSpinnerTick(80);
|
|
133219
133280
|
}
|
|
133220
133281
|
stopSpinner() {
|
|
133221
|
-
if (this.
|
|
133222
|
-
|
|
133223
|
-
this.
|
|
133282
|
+
if (this.spinnerTimer === void 0) return;
|
|
133283
|
+
clearTimeout(this.spinnerTimer);
|
|
133284
|
+
this.spinnerTimer = void 0;
|
|
133224
133285
|
}
|
|
133225
133286
|
};
|
|
133226
133287
|
//#endregion
|
|
@@ -136112,7 +136173,11 @@ function findRevokeAnchorComponentIndex(children, count) {
|
|
|
136112
136173
|
function removeRevokeContextComponents(children, startIndex) {
|
|
136113
136174
|
for (let i = children.length - 1; i >= startIndex; i--) {
|
|
136114
136175
|
const child = children[i];
|
|
136115
|
-
if (child !== void 0 && isRevokeContextComponent(child))
|
|
136176
|
+
if (child !== void 0 && isRevokeContextComponent(child)) {
|
|
136177
|
+
const disposable = child;
|
|
136178
|
+
if (typeof disposable.dispose === "function") disposable.dispose();
|
|
136179
|
+
children.splice(i, 1);
|
|
136180
|
+
}
|
|
136116
136181
|
}
|
|
136117
136182
|
}
|
|
136118
136183
|
function isRevokeAnchorComponent(child) {
|
|
@@ -137974,6 +138039,8 @@ var MoonLoader = class extends Text {
|
|
|
137974
138039
|
ui;
|
|
137975
138040
|
colorFn;
|
|
137976
138041
|
label;
|
|
138042
|
+
/** Wall-clock time of the last frame advance, for drift-free scheduling. */
|
|
138043
|
+
lastTickAt = 0;
|
|
137977
138044
|
constructor(ui, colorFn, label = "") {
|
|
137978
138045
|
super("", 1, 0);
|
|
137979
138046
|
this.ui = ui;
|
|
@@ -137982,18 +138049,44 @@ var MoonLoader = class extends Text {
|
|
|
137982
138049
|
this.start();
|
|
137983
138050
|
}
|
|
137984
138051
|
start() {
|
|
138052
|
+
this.lastTickAt = performance.now();
|
|
137985
138053
|
this.updateDisplay();
|
|
137986
|
-
this.
|
|
137987
|
-
this.currentFrame = (this.currentFrame + 1) % BRAILLE_SPINNER_FRAMES.length;
|
|
137988
|
-
this.updateDisplay();
|
|
137989
|
-
}, 80);
|
|
138054
|
+
this.scheduleTick(80, 80);
|
|
137990
138055
|
}
|
|
137991
138056
|
stop() {
|
|
137992
138057
|
if (this.intervalId) {
|
|
137993
|
-
|
|
138058
|
+
clearTimeout(this.intervalId);
|
|
137994
138059
|
this.intervalId = null;
|
|
137995
138060
|
}
|
|
137996
138061
|
}
|
|
138062
|
+
dispose() {
|
|
138063
|
+
this.stop();
|
|
138064
|
+
}
|
|
138065
|
+
/**
|
|
138066
|
+
* setTimeout self-rescheduling chain with drift-free frame advancement and
|
|
138067
|
+
* paint-cost backpressure (same pattern as the pi-tui Loader): a slow tick
|
|
138068
|
+
* defers the next one by `max(0, interval - cost, cost × 9)` instead of
|
|
138069
|
+
* stacking intervals, keeping the spinner ≤ ~10% CPU under slow writes.
|
|
138070
|
+
*/
|
|
138071
|
+
scheduleTick(intervalMs, delayMs) {
|
|
138072
|
+
const timer = setTimeout(() => {
|
|
138073
|
+
if (this.intervalId !== timer) return;
|
|
138074
|
+
const startedAt = performance.now();
|
|
138075
|
+
const elapsed = startedAt - this.lastTickAt;
|
|
138076
|
+
if (elapsed >= intervalMs) {
|
|
138077
|
+
const steps = Math.floor(elapsed / intervalMs);
|
|
138078
|
+
this.currentFrame = (this.currentFrame + steps) % BRAILLE_SPINNER_FRAMES.length;
|
|
138079
|
+
this.lastTickAt += steps * intervalMs;
|
|
138080
|
+
this.updateDisplay();
|
|
138081
|
+
}
|
|
138082
|
+
const frameCostMs = performance.now() - startedAt;
|
|
138083
|
+
if (this.intervalId !== timer) return;
|
|
138084
|
+
const cadenceDelayMs = Math.max(0, intervalMs - frameCostMs);
|
|
138085
|
+
const backpressureDelayMs = frameCostMs * 9;
|
|
138086
|
+
this.scheduleTick(intervalMs, Math.max(cadenceDelayMs, backpressureDelayMs));
|
|
138087
|
+
}, delayMs);
|
|
138088
|
+
this.intervalId = timer;
|
|
138089
|
+
}
|
|
137997
138090
|
setLabel(label) {
|
|
137998
138091
|
this.label = label;
|
|
137999
138092
|
this.updateDisplay();
|
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-Bqc3MVGh.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);
|