scream-code 0.15.6 → 0.15.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 +7 -4
- package/dist/{app-Y2DCZTWP.mjs → app-Bbg_nJTR.mjs} +98 -36
- package/dist/{dispatch-jQiqBKV2.mjs → dispatch-BaAsj0v5.mjs} +829 -147
- package/dist/{dispatch-CkPcMk4b.mjs → dispatch-CEK-syAX.mjs} +1 -1
- package/dist/main.mjs +1 -1
- package/dist/public/assets/{index-ChLLVxTo.js → index-DjlCHEg8.js} +19 -19
- package/dist/public/assets/index-DjlCHEg8.js.map +1 -0
- package/dist/public/index.html +1 -1
- package/dist/{text-input-dialog-DJwYNHcs.mjs → text-input-dialog-BBSjCM5z.mjs} +1 -1
- package/dist/{text-input-dialog-LOMBSusF.mjs → text-input-dialog-C5pDKZ-c.mjs} +35 -21
- package/package.json +1 -1
- package/dist/public/assets/index-ChLLVxTo.js.map +0 -1
package/README.md
CHANGED
|
@@ -48,22 +48,24 @@ When Scream wants to modify files or run commands, an approval panel pops up —
|
|
|
48
48
|
|
|
49
49
|
### Features
|
|
50
50
|
|
|
51
|
-
- **Goal Loop** — autonomous, goal-driven execution with an independent judge agent and token/time
|
|
51
|
+
- **Goal Loop** — autonomous, goal-driven execution with an independent judge agent. Rejections must name concrete gaps; evidence gaps self-repair for up to 3 rounds, subjective calls park for your decision (with a written report), and token/time budgets bound the loop.
|
|
52
|
+
- **TUI Sidebar** — four live panels: workspace Git diff summary (green adds / red deletes), per-session token accounting (cache-hit / cache-miss / output), 8 sub-agent slots with real-time states (idle / working / outputting / messaging / reworking), and Goal status with judge state (awaiting / judging / adjudicated).
|
|
52
53
|
- **Wolfpack** — unlimited parallel sub-agents (coder / explore / plan / verify / reviewer / oracle / writer / worker).
|
|
53
|
-
- **Subagent Collaboration** —
|
|
54
|
+
- **Subagent Collaboration** — delegate to specialist sub-agents and stay in control: they **ask the lead agent for guidance mid-task instead of guessing when blocked**, request a handoff when a different specialist fits, take mid-task redirects or follow-up notes, return structured JSON when asked, and can be confined to a safe mode (read-only / edit-only / commands-allowed) so they never overstep your limits.
|
|
55
|
+
- **Bot Mode (`/bot`)** — unattended execution: reversible work (reads, in-workspace edits, read-only commands) runs freely, while irreversible actions (push / publish / delete / sensitive files / unclassified operations) are automatically denied and queued for your review — with the reason fed back to the model so it stops retrying.
|
|
54
56
|
- **Persistent Memory** — structured pain-point memory with FTS5 full-text + tag + vector retrieval, shared across sessions.
|
|
55
57
|
- **Local Knowledge Graph** — SAG-based visual knowledge base for multi-hop reasoning; import your own docs anytime.
|
|
56
58
|
- **RLM Mode** — persistent Python workspace for long-running tasks, with unlimited recursive sub-agents.
|
|
57
59
|
- **Session Trace** — `/trace` exports any session as a self-contained, offline interactive HTML timeline.
|
|
58
60
|
- **Context Search** — `/search` (Ctrl+Shift+F) full-screen keyword search over the conversation.
|
|
59
61
|
- **High Cache Hit Rate** — per-session HitR in the status bar, tuned across compatible protocols to maximize cache hits without compromising quality.
|
|
60
|
-
- **MCP / Skills / 130+ providers** — all DIY-configurable; ships with browser
|
|
62
|
+
- **MCP / Skills / 130+ providers** — all DIY-configurable; ships with browser automation and macOS desktop automation.
|
|
61
63
|
- **Self-Evolving Plugins** — a built-in `ManagePlugin` tool lets the agent find, make, and install add-on skills/MCP servers itself and hot-apply them to the running session: nothing executes until an approved activate, a circuit breaker reclaims a plugin after repeated failures, immune memory warns before reinstalling a source that already broke, and upgrades keep a rollback-ready backup.
|
|
62
64
|
- **Remote Control** — drive Scream from WeChat, Feishu, Slack, DingTalk, QQ, Telegram, Discord via cc-connect.
|
|
63
65
|
|
|
64
66
|
### Slash Commands
|
|
65
67
|
|
|
66
|
-
Type `/` in the input to browse. All
|
|
68
|
+
Type `/` in the input to browse. All 48 commands:
|
|
67
69
|
|
|
68
70
|
<details>
|
|
69
71
|
<summary>Full command reference (click to expand)</summary>
|
|
@@ -74,6 +76,7 @@ Type `/` in the input to browse. All 47 commands:
|
|
|
74
76
|
| `/auto` | Toggle auto permission mode |
|
|
75
77
|
| `/yes` (`/yolo`) | Toggle auto-approve mode |
|
|
76
78
|
| `/ask` | Toggle read-only Q&A mode |
|
|
79
|
+
| `/bot` | Unattended bot mode: reversible actions auto-approve, irreversible ones park for review |
|
|
77
80
|
| `/goal [objective]` | View/manage auto goals |
|
|
78
81
|
| `/wolfpack` (`/wp`) | Toggle wolfpack mode — auto-approve + batch concurrency |
|
|
79
82
|
| `/rlm` | RLM mode: persistent Python workspace, unlimited recursive subagents |
|
|
@@ -4,8 +4,8 @@ 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
|
|
8
|
-
import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-
|
|
7
|
+
import { $t as argsRecord, A as renderDiffLinesClustered, An as detectShellEnvironment, At as DISABLE_TERMINAL_THEME_REPORTING, B as BackgroundAgentStatusComponent, Bn as fetchCatalog, Bt as TERMINAL_THEME_DARK, Cn as startManualEmbeddingDownload, Ct as createMarkdownTheme, D as toggleEmptySessionHint, Dn as TuiLikePreferencesSchema, Dt as detectTerminalTheme, E as isTurnElapsedEnabled, En as TuiConfigParseError, Et as getColorPalette, F as estimateTokens, Fn as CLI_COMMAND_NAME, Ft as OSC11_RESPONSE_PREFIX, G as getBreathingFrame, Gn as MemoryMemoStore, Gt as lerpGradient, H as AgentGroupComponent, Hn as ScreamHarness, Ht as isBusy, I as getSharedSpeedTracker, In as CLI_UI_MODE, It as OSC11_RESPONSE_PREFIX_NO_ESC, J as refineGoal, Jn as resolveGlobalLogPath, K as resetBreathingClock, Kn as flushDiagnosticLogs, L as SkillActivationComponent, Ln as CLI_USER_AGENT_PRODUCT, Lt as QUERY_TERMINAL_THEME, M as langFromPath, Mn as getInputHistoryFile, Mt as ENABLE_TERMINAL_THEME_REPORTING, N as CachedContainer, Nn as getLogDir, Nt as OSC11_QUERY, O as ToolCallComponent, On as loadTuiConfig, Ot as parseOsc11BackgroundTheme, P as ThinkingComponent, Pn as detectInstallSource, Pt as OSC11_RESPONSE, Qn as SCREAM_ERROR_INFO, Qt as appendStreamingArgsPreview, R as ReadGroupComponent, Rn as PRODUCT_NAME, Rt as TERMINAL_FOCUS_IN, S as getDaemonInstructions, Sn as isEmbeddingModelCached, St as createEditorTheme, T as isEmptySessionHintDismissed, Tn as PULSE_WAVE_FRAMES, Tt as contrastTextHex, U as WelcomeComponent, Ut as isStreaming, V as AssistantMessageComponent, Vn as saveCatalogCache, Vt as TERMINAL_THEME_LIGHT, W as BREATHE_CYCLE_MS, Wn as resolveScreamHome, Wt as FooterComponent, Xn as isOrphanedToolCallError, Xt as printableChar, Yn as isScreamError, Zn as ErrorCodes, Zt as STATUS_BULLET, _ as refreshUpdateCache, _n as BUILTIN_SLASH_COMMANDS, _t as supportsBalance, an as truncateErrorMessage, b as readJsonlFile, bn as setExperimentalFlags, c as hasDispose, cn as EXIT_CONFIRM_WINDOW_MS, d as formatMemoryMemoForInjection, dn as TIP_ROTATION_INTERVAL_MS, en as formatErrorMessage, et as toTerminalHyperlink, fn as getCtrlCHint, g as selectUpdateTarget, gn as buildSkillSlashCommands, gt as refreshProviderBalance, hn as getNoActiveSessionMessage, i as buildRoleAdditionalText, in as stringValue, j as highlightLines, jn as getDataDir, jt as ENABLE_TERMINAL_FOCUS_REPORTING, k as renderDiffLines, kn as saveTuiConfig, kt as DISABLE_TERMINAL_FOCUS_REPORTING, l as isPlanExpandable, ln as MAIN_AGENT_ID, lt as handlePlanCommand, mn as getLlmNotSetMessage, n as clearEvalPanelState, nn as parseStreamingArgs, nt as getModelCycleLevel, on as CHARS_PER_TOKEN, pn as getCtrlDHint, q as clearGoalState, qn as log, r as openUrl, rn as serializeToolResultOutput, s as disposeChildren, sn as EMPTY_SESSION_HINT_URL, st as handleFusionPlanCommand, t as dispatchInput, tn as isTodoItemShape, tt as changeThinkingLevel, u as MoonLoader, un as SESSION_TIPS, v as readUpdateCache, vn as sortSlashCommands, vt as clearInfoPanelState, w as UserMessageComponent, wn as PIXEL_PULSE_FRAMES, wt as createThemeStyles, xn as getKnowledgeStore, xt as resolveThemeSync, y as appendJsonlLine, yn as isExperimentalFlagEnabled, z as parseReadGroupOutput, zn as DEFAULT_CATALOG_URL, zt as TERMINAL_FOCUS_OUT } from "./dispatch-BaAsj0v5.mjs";
|
|
8
|
+
import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-C5pDKZ-c.mjs";
|
|
9
9
|
import { createRequire } from "node:module";
|
|
10
10
|
import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
11
11
|
import { access, chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
@@ -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.8"),
|
|
36
36
|
channel: optionalBuildString(""),
|
|
37
37
|
commit: optionalBuildString(""),
|
|
38
38
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -2913,10 +2913,12 @@ var SessionEventHandler = class {
|
|
|
2913
2913
|
this.host.streamingUI.flushNow();
|
|
2914
2914
|
this.maybeShowDebugTiming(event);
|
|
2915
2915
|
this.drainQueuedMessagesIntoSteer();
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2916
|
+
const prev = this.host.state.appState.sessionUsage;
|
|
2917
|
+
const apiCalls = this.host.state.appState.sessionApiCalls + 1;
|
|
2918
|
+
this.host.setAppState(event.usage === void 0 ? { sessionApiCalls: apiCalls } : {
|
|
2919
|
+
sessionUsage: prev === void 0 ? event.usage : addTokenUsage(prev, event.usage),
|
|
2920
|
+
sessionApiCalls: apiCalls
|
|
2921
|
+
});
|
|
2920
2922
|
if (event.finishReason !== "max_tokens") return;
|
|
2921
2923
|
const title = this.host.streamingUI.markStepTruncated(String(event.turnId), event.step) > 0 ? t("handler.max_tokens_truncated") : t("handler.max_tokens_no_tool");
|
|
2922
2924
|
const detail = this.isAnthropicSessionActive() ? t("handler.max_tokens_hint") : void 0;
|
|
@@ -2930,7 +2932,8 @@ var SessionEventHandler = class {
|
|
|
2930
2932
|
reconnectMaxAttempts: event.maxAttempts,
|
|
2931
2933
|
reconnectDelayMs: event.delayMs,
|
|
2932
2934
|
reconnectStatusCode: event.statusCode,
|
|
2933
|
-
reconnectErrorName: event.errorName
|
|
2935
|
+
reconnectErrorName: event.errorName,
|
|
2936
|
+
sessionApiCalls: this.host.state.appState.sessionApiCalls + 1
|
|
2934
2937
|
});
|
|
2935
2938
|
}
|
|
2936
2939
|
maybeShowDebugTiming(event) {
|
|
@@ -6709,6 +6712,24 @@ function displayWidth(text) {
|
|
|
6709
6712
|
function padLabel(label, target) {
|
|
6710
6713
|
return label + " ".repeat(Math.max(0, target - displayWidth(label)));
|
|
6711
6714
|
}
|
|
6715
|
+
/** Pad `value` on the LEFT to `target` display columns (CJK-aware), which is
|
|
6716
|
+
* what right-aligning a numeric column means in terminal space. */
|
|
6717
|
+
function padValue(value, target) {
|
|
6718
|
+
return " ".repeat(Math.max(0, target - displayWidth(value))) + value;
|
|
6719
|
+
}
|
|
6720
|
+
function alignMetricRows(rows, opts = {}) {
|
|
6721
|
+
const gap = opts.gap ?? 2;
|
|
6722
|
+
const labels = [...rows.map(([label]) => label), ...opts.extraLabels ?? []];
|
|
6723
|
+
const labelCols = labels.length === 0 ? 0 : Math.max(...labels.map((label) => displayWidth(label)));
|
|
6724
|
+
const measured = rows.length === 0 ? 0 : Math.max(...rows.map(([, value]) => displayWidth(value)));
|
|
6725
|
+
const valueCols = opts.maxValueCols === void 0 ? measured : Math.min(measured, Math.max(0, opts.maxValueCols));
|
|
6726
|
+
const separator = " ".repeat(Math.max(0, gap));
|
|
6727
|
+
return {
|
|
6728
|
+
labelCols,
|
|
6729
|
+
valueCols,
|
|
6730
|
+
rows: rows.map(([label, value]) => [padLabel(label, labelCols) + separator, padValue(truncateToWidth(value, valueCols), valueCols)])
|
|
6731
|
+
};
|
|
6732
|
+
}
|
|
6712
6733
|
//#endregion
|
|
6713
6734
|
//#region src/tui/components/sidebar/panels/session-panel.ts
|
|
6714
6735
|
function formatDuration(ms) {
|
|
@@ -6730,10 +6751,31 @@ function formatCount$1(n) {
|
|
|
6730
6751
|
return n.toLocaleString("en-US");
|
|
6731
6752
|
}
|
|
6732
6753
|
/**
|
|
6733
|
-
*
|
|
6734
|
-
*
|
|
6735
|
-
*
|
|
6736
|
-
|
|
6754
|
+
* Compact token form for narrow sidebars: 2,267,680,102 → `22.7亿` (zh) or
|
|
6755
|
+
* `2.3B` (en). Used only when the thousands-separated form cannot fit, so a
|
|
6756
|
+
* narrow sidebar keeps every value readable instead of cutting digits.
|
|
6757
|
+
*/
|
|
6758
|
+
function formatCompact(n) {
|
|
6759
|
+
if (getLocale() === "zh") {
|
|
6760
|
+
if (n >= 9995e4) return `${(n / 1e8).toFixed(1)}亿`;
|
|
6761
|
+
if (n >= 9500) return `${Math.round(n / 1e4)}万`;
|
|
6762
|
+
return String(n);
|
|
6763
|
+
}
|
|
6764
|
+
if (n >= 9995e5) return `${(n / 1e9).toFixed(1)}B`;
|
|
6765
|
+
if (n >= 999500) return `${(n / 1e6).toFixed(1)}M`;
|
|
6766
|
+
if (n >= 1e3) return `${Math.round(n / 1e3)}K`;
|
|
6767
|
+
return String(n);
|
|
6768
|
+
}
|
|
6769
|
+
/** True when a two-column grid fits `width` display columns. */
|
|
6770
|
+
function gridFits(rows, width) {
|
|
6771
|
+
const grid = alignMetricRows(rows);
|
|
6772
|
+
return grid.labelCols + 2 + grid.valueCols <= width;
|
|
6773
|
+
}
|
|
6774
|
+
/**
|
|
6775
|
+
* Session summary, live-rendered each frame as a strict two-column table:
|
|
6776
|
+
* one field per row, labels sharing a left column, values sharing a right
|
|
6777
|
+
* edge. Uptime derives from `startedAt` so it ticks between data updates;
|
|
6778
|
+
* every other value comes from the snapshot in getData().
|
|
6737
6779
|
*/
|
|
6738
6780
|
var SessionPanelContent = class {
|
|
6739
6781
|
ctx;
|
|
@@ -6749,19 +6791,25 @@ var SessionPanelContent = class {
|
|
|
6749
6791
|
const label = (s) => chalk.hex(this.colors.textDim)(s);
|
|
6750
6792
|
const value = (s) => chalk.hex(this.colors.text)(s);
|
|
6751
6793
|
const now = Date.now();
|
|
6752
|
-
const
|
|
6753
|
-
[t("sidebar.tokens"),
|
|
6754
|
-
[t("sidebar.tokens_cache_hit"),
|
|
6755
|
-
[t("sidebar.tokens_cache_miss"),
|
|
6756
|
-
[t("sidebar.tokens_output"),
|
|
6757
|
-
[t("sidebar.uptime"), formatDuration(now - stats.startedAt)]
|
|
6794
|
+
const tokenRows = [
|
|
6795
|
+
[t("sidebar.tokens"), stats.tokensTotal],
|
|
6796
|
+
[t("sidebar.tokens_cache_hit"), stats.tokensInputCacheHit],
|
|
6797
|
+
[t("sidebar.tokens_cache_miss"), stats.tokensInputCacheMiss],
|
|
6798
|
+
[t("sidebar.tokens_output"), stats.tokensOutput]
|
|
6758
6799
|
];
|
|
6759
|
-
const
|
|
6760
|
-
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6800
|
+
const countRows = [
|
|
6801
|
+
[t("sidebar.uptime"), formatDuration(now - stats.startedAt)],
|
|
6802
|
+
[t("sidebar.turns"), formatCount$1(stats.turns)],
|
|
6803
|
+
[t("sidebar.tools"), formatCount$1(stats.toolCalls)],
|
|
6804
|
+
[t("sidebar.calls"), formatCount$1(stats.apiCalls)],
|
|
6805
|
+
[t("sidebar.compacts"), formatCount$1(stats.compactions)]
|
|
6806
|
+
];
|
|
6807
|
+
const withTokens = (compact) => [...tokenRows.map(([name, n]) => [name, compact ? formatCompact(n) : formatCount$1(n)]), ...countRows];
|
|
6808
|
+
const full = withTokens(false);
|
|
6809
|
+
const rows = gridFits(full, width) ? full : withTokens(true);
|
|
6810
|
+
const probe = alignMetricRows(rows);
|
|
6811
|
+
const budget = Math.max(1, width - probe.labelCols - 2);
|
|
6812
|
+
return (probe.valueCols <= budget ? probe : alignMetricRows(rows, { maxValueCols: budget })).rows.map(([k, v]) => label(k) + value(v));
|
|
6765
6813
|
}
|
|
6766
6814
|
};
|
|
6767
6815
|
const sessionPanel = {
|
|
@@ -6890,9 +6938,17 @@ var GoalPanelContent = class {
|
|
|
6890
6938
|
[t("sidebar.goal_wall"), formatWallClock(wallMs)],
|
|
6891
6939
|
[t("sidebar.goal_judge"), judgeText(goal.judge)]
|
|
6892
6940
|
];
|
|
6893
|
-
const
|
|
6894
|
-
|
|
6895
|
-
|
|
6941
|
+
const hasCriterion = goal.completionCriterion !== null;
|
|
6942
|
+
const criterionLabel = t("sidebar.goal_criterion");
|
|
6943
|
+
const extraLabels = hasCriterion ? [criterionLabel] : [];
|
|
6944
|
+
const probe = alignMetricRows(rows, { extraLabels });
|
|
6945
|
+
const budget = Math.max(4, width - probe.labelCols - 2);
|
|
6946
|
+
const grid = probe.valueCols <= budget ? probe : alignMetricRows(rows, {
|
|
6947
|
+
extraLabels,
|
|
6948
|
+
maxValueCols: budget
|
|
6949
|
+
});
|
|
6950
|
+
for (const [label, value] of grid.rows) lines.push(dim(label) + text(value));
|
|
6951
|
+
if (hasCriterion) lines.push(dim(padLabel(criterionLabel, grid.labelCols) + " ".repeat(2)) + truncateToWidth(text(goal.completionCriterion), budget));
|
|
6896
6952
|
return lines;
|
|
6897
6953
|
}
|
|
6898
6954
|
/** State badge: judging wins over everything; otherwise map the snapshot
|
|
@@ -7740,7 +7796,7 @@ var LifecycleController = class LifecycleController {
|
|
|
7740
7796
|
const usage = appState.sessionUsage;
|
|
7741
7797
|
const subagentUsage = appState.subagentUsage;
|
|
7742
7798
|
const memo = this.sidebarStatsMemo;
|
|
7743
|
-
if (memo !== void 0 && memo.length === entries.length && memo.compactions === appState.autoCompactionCount && memo.usage === usage && memo.subagentUsage === subagentUsage) return memo.stats;
|
|
7799
|
+
if (memo !== void 0 && memo.length === entries.length && memo.compactions === appState.autoCompactionCount && memo.usage === usage && memo.subagentUsage === subagentUsage && memo.apiCalls === appState.sessionApiCalls) return memo.stats;
|
|
7744
7800
|
let turns = 0;
|
|
7745
7801
|
let toolCalls = 0;
|
|
7746
7802
|
for (const entry of entries) {
|
|
@@ -7752,8 +7808,8 @@ var LifecycleController = class LifecycleController {
|
|
|
7752
7808
|
const stats = {
|
|
7753
7809
|
turns,
|
|
7754
7810
|
toolCalls,
|
|
7755
|
-
messages: entries.length,
|
|
7756
7811
|
compactions: appState.autoCompactionCount,
|
|
7812
|
+
apiCalls: appState.sessionApiCalls,
|
|
7757
7813
|
tokensTotal: LifecycleController.sumTokens(usage) + subagentOutput,
|
|
7758
7814
|
tokensInputCacheHit: usage.inputCacheRead,
|
|
7759
7815
|
tokensInputCacheMiss: usage.inputOther + usage.inputCacheCreation,
|
|
@@ -7765,6 +7821,7 @@ var LifecycleController = class LifecycleController {
|
|
|
7765
7821
|
compactions: appState.autoCompactionCount,
|
|
7766
7822
|
usage,
|
|
7767
7823
|
subagentUsage,
|
|
7824
|
+
apiCalls: appState.sessionApiCalls,
|
|
7768
7825
|
stats
|
|
7769
7826
|
};
|
|
7770
7827
|
return stats;
|
|
@@ -10593,10 +10650,11 @@ const PRUNE_EMPTY_SESSION_GRACE_MS = 300 * 1e3;
|
|
|
10593
10650
|
function isPrunableEmptySession(summary, now, graceMs = PRUNE_EMPTY_SESSION_GRACE_MS) {
|
|
10594
10651
|
if (summary.archived) return false;
|
|
10595
10652
|
if (summary.lastPrompt !== void 0) return false;
|
|
10596
|
-
if (
|
|
10653
|
+
if (hasRealTitle(summary.title)) return false;
|
|
10597
10654
|
return now - summary.updatedAt > graceMs;
|
|
10598
10655
|
}
|
|
10599
|
-
|
|
10656
|
+
/** True when the title is a user-meaningful title (not missing / placeholder). */
|
|
10657
|
+
function hasRealTitle(title) {
|
|
10600
10658
|
return typeof title === "string" && title.trim().length > 0 && title !== "New Session";
|
|
10601
10659
|
}
|
|
10602
10660
|
/**
|
|
@@ -13046,6 +13104,7 @@ function createInitialAppState(input) {
|
|
|
13046
13104
|
inputCacheRead: 0,
|
|
13047
13105
|
inputCacheCreation: 0
|
|
13048
13106
|
},
|
|
13107
|
+
sessionApiCalls: 0,
|
|
13049
13108
|
providerBalance: null,
|
|
13050
13109
|
balanceUpdatedAt: 0,
|
|
13051
13110
|
isCompacting: false,
|
|
@@ -13465,6 +13524,7 @@ var ScreamTUI = class {
|
|
|
13465
13524
|
inputCacheRead: 0,
|
|
13466
13525
|
inputCacheCreation: 0
|
|
13467
13526
|
};
|
|
13527
|
+
this.state.appState.sessionApiCalls = 0;
|
|
13468
13528
|
}
|
|
13469
13529
|
if (planModeChanged || sessionChanged) {
|
|
13470
13530
|
this.updateEditorBorderHighlight();
|
|
@@ -13572,7 +13632,7 @@ var ScreamTUI = class {
|
|
|
13572
13632
|
const card = new OnboardingCardComponent({
|
|
13573
13633
|
colors: this.state.theme.colors,
|
|
13574
13634
|
onConfigure: () => {
|
|
13575
|
-
import("./dispatch-
|
|
13635
|
+
import("./dispatch-CEK-syAX.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
|
|
13576
13636
|
this.restoreEditor();
|
|
13577
13637
|
onDone?.();
|
|
13578
13638
|
});
|
|
@@ -16674,8 +16734,9 @@ var WebSession = class {
|
|
|
16674
16734
|
}
|
|
16675
16735
|
return;
|
|
16676
16736
|
case "auto":
|
|
16677
|
-
case "yes":
|
|
16678
|
-
|
|
16737
|
+
case "yes":
|
|
16738
|
+
case "bot": {
|
|
16739
|
+
const mode = command === "auto" ? "auto" : command === "bot" ? "bot" : "yolo";
|
|
16679
16740
|
try {
|
|
16680
16741
|
await this.session.setPermission(mode);
|
|
16681
16742
|
this.permission = mode;
|
|
@@ -17412,9 +17473,10 @@ var SessionManager = class {
|
|
|
17412
17473
|
list() {
|
|
17413
17474
|
return Array.from(this.sessions.values()).map((s) => s.getListItem()).toSorted((a, b) => b.createdAt - a.createdAt);
|
|
17414
17475
|
}
|
|
17415
|
-
/** True when any session has an agent turn (main or subagent) in flight
|
|
17476
|
+
/** True when any session has an agent turn (main or subagent) in flight, or
|
|
17477
|
+
* any session runs in unattended bot mode (defers idle exit). */
|
|
17416
17478
|
anyBusy() {
|
|
17417
|
-
return Array.from(this.sessions.values()).some((s) => s.isTurnActive);
|
|
17479
|
+
return Array.from(this.sessions.values()).some((s) => s.isTurnActive || s.permission === "bot");
|
|
17418
17480
|
}
|
|
17419
17481
|
async delete(sessionId) {
|
|
17420
17482
|
const ws = this.sessions.get(sessionId);
|