scream-code 0.16.4 → 0.16.6
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-C0OLgL_b.mjs → app-D9oJ-Y8W.mjs} +224 -49
- package/dist/{dispatch-C7ujqj4p.mjs → dispatch-dDbUBD7J.mjs} +1 -1
- package/dist/{dispatch-La1sAZPF.mjs → dispatch-fjwbqaYI.mjs} +1275 -307
- package/dist/main.mjs +1 -1
- package/dist/{text-input-dialog-CNhL-3wm.mjs → text-input-dialog-Cj0egbsU.mjs} +1 -1
- package/dist/{text-input-dialog--J3ngWFv.mjs → text-input-dialog-DBlx8pMR.mjs} +24 -6
- package/package.json +2 -2
|
@@ -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 { $n as
|
|
8
|
-
import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog
|
|
7
|
+
import { $n as appendSessionIndexEntry, $t as SubagentSlots, A as langFromPath, An as hasEmbeddingModelCache, At as toggleEmptySessionHint, B as charsForTokenBudget, Bn as getInputHistoryFile, Bt as OSC11_QUERY, C as getDaemonInstructions, Cn as buildSkillSlashCommands, D as renderDiffLines, Dn as setExperimentalFlags, Dt as createMarkdownTheme, E as ToolCallComponent, En as isExperimentalFlagEnabled, Et as createEditorTheme, F as replaceTabs, Fn as TuiLikePreferencesSchema, Ft as parseOsc11BackgroundTheme, G as WelcomeComponent, Gn as CLI_USER_AGENT_PRODUCT, Gt as TERMINAL_FOCUS_IN, H as getSharedSpeedTracker, Hn as detectInstallSource, Ht as OSC11_RESPONSE_PREFIX, I as sanitizeShellOutput, In as loadTuiConfig, It as DISABLE_TERMINAL_FOCUS_REPORTING, J as resetBreathingClock, Jn as fetchCatalog, Jt as TERMINAL_THEME_LIGHT, K as BREATHE_CYCLE_MS, Kn as PRODUCT_NAME, Kt as TERMINAL_FOCUS_OUT, L as SkillActivationComponent, Ln as saveTuiConfig, Lt as DISABLE_TERMINAL_THEME_REPORTING, M as ThinkingComponent, Mn as PIXEL_PULSE_FRAMES, Mt as contrastTextHex, N as NoticeMessageComponent, Nn as PULSE_WAVE_FRAMES, Nt as getColorPalette, O as renderDiffLinesClustered, On as embeddingFailureDetail, Ot as isEmptySessionHintDismissed, P as StatusMessageComponent, Pn as TuiConfigParseError, Pt as detectTerminalTheme, Qn as normalizeWorkDir, Qt as lerpGradient, R as AssistantMessageComponent, Rn as detectShellEnvironment, Rt as ENABLE_TERMINAL_FOCUS_REPORTING, Sn as getNoActiveSessionMessage, St as clearInfoPanelState, T as UserMessageComponent, Tn as sortSlashCommands, Tt as resolveThemeSync, U as BackgroundAgentStatusComponent, Un as CLI_COMMAND_NAME, Ut as OSC11_RESPONSE_PREFIX_NO_ESC, V as estimateTokens, Vn as getLogDir, Vt as OSC11_RESPONSE, W as AgentGroupComponent, Wn as CLI_UI_MODE, Wt as QUERY_TERMINAL_THEME, X as clearGoalState, Xn as ScreamHarness, Xt as isStreaming, Y as CompactionComponent, Yn as saveCatalogCache, Yt as isBusy, Z as refineGoal, Zn as encodeWorkDirKey, Zt as FooterComponent, _ as selectUpdateTarget, _n as SESSION_TIPS, an as STATUS_BULLET, ar as flushDiagnosticLogs, at as changeThinkingLevel, b as appendJsonlLine, bn as getCtrlDHint, bt as refreshProviderBalance, c as hasDispose, cn as formatErrorMessage, cr as isScreamError, d as MoonLoader, dn as serializeToolResultOutput, dr as SCREAM_ERROR_INFO, dt as handleFusionPlanCommand, er as readSessionIndex, f as formatMemoryMemoForInjection, fn as stringValue, gn as MAIN_AGENT_ID, hn as EXIT_CONFIRM_WINDOW_MS, i as buildRoleAdditionalText, in as printableChar, ir as MemoryMemoStore, it as toTerminalHyperlink, j as CachedContainer, jn as startManualEmbeddingDownload, jt as createThemeStyles, k as highlightLines, kn as getKnowledgeStore, kt as isTurnElapsedEnabled, l as isExpandable, ln as isTodoItemShape, lr as isOrphanedToolCallError, mn as EMPTY_SESSION_HINT_URL, n as clearEvalPanelState, on as appendStreamingArgsPreview, or as log, ot as getModelCycleLevel, pn as truncateErrorMessage, pt as handlePlanCommand, q as getBreathingFrame, qn as DEFAULT_CATALOG_URL, qt as TERMINAL_THEME_DARK, r as openUrl, rr as resolveScreamHome, rt as isInternalMessage, s as disposeChildren, sn as argsRecord, sr as resolveGlobalLogPath, t as dispatchInput, tr as removeSessionIndexEntry, u as isPlanExpandable, un as parseStreamingArgs, ur as ErrorCodes, v as refreshUpdateCache, vn as TIP_ROTATION_INTERVAL_MS, wn as BUILTIN_SLASH_COMMANDS, x as readJsonlFile, xn as getLlmNotSetMessage, xt as supportsBalance, y as readUpdateCache, yn as getCtrlCHint, z as ActivityGroupComponent, zn as getDataDir, zt as ENABLE_TERMINAL_THEME_REPORTING } from "./dispatch-fjwbqaYI.mjs";
|
|
8
|
+
import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-DBlx8pMR.mjs";
|
|
9
9
|
import { createRequire } from "node:module";
|
|
10
10
|
import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
11
11
|
import { access, appendFile, 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.16.
|
|
35
|
+
version: optionalBuildString("0.16.6"),
|
|
36
36
|
channel: optionalBuildString(""),
|
|
37
37
|
commit: optionalBuildString(""),
|
|
38
38
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -1986,7 +1986,8 @@ function formatBackgroundAgentTranscript(phase, meta, extras = void 0) {
|
|
|
1986
1986
|
return {
|
|
1987
1987
|
phase,
|
|
1988
1988
|
headline,
|
|
1989
|
-
detail: detailParts.length > 0 ? detailParts.join(" · ") : void 0
|
|
1989
|
+
detail: detailParts.length > 0 ? detailParts.join(" · ") : void 0,
|
|
1990
|
+
trackingId: meta.agentId
|
|
1990
1991
|
};
|
|
1991
1992
|
}
|
|
1992
1993
|
//#endregion
|
|
@@ -2209,7 +2210,8 @@ function formatBackgroundTaskTranscript(info) {
|
|
|
2209
2210
|
return {
|
|
2210
2211
|
phase: phaseFromStatus(info.status),
|
|
2211
2212
|
headline: headlineFor(info),
|
|
2212
|
-
detail: detailFor(info)
|
|
2213
|
+
detail: detailFor(info),
|
|
2214
|
+
trackingId: info.taskId
|
|
2213
2215
|
};
|
|
2214
2216
|
}
|
|
2215
2217
|
//#endregion
|
|
@@ -2910,6 +2912,7 @@ var SessionEventHandler = class {
|
|
|
2910
2912
|
}
|
|
2911
2913
|
handleStepCompleted(event) {
|
|
2912
2914
|
this.host.streamingUI.flushNow();
|
|
2915
|
+
this.host.streamingUI.flushPendingApprovals();
|
|
2913
2916
|
this.maybeShowDebugTiming(event);
|
|
2914
2917
|
this.recordProviderLatency(event);
|
|
2915
2918
|
this.drainQueuedMessagesIntoSteer();
|
|
@@ -2936,6 +2939,24 @@ var SessionEventHandler = class {
|
|
|
2936
2939
|
sessionApiCalls: this.host.state.appState.sessionApiCalls + 1
|
|
2937
2940
|
});
|
|
2938
2941
|
}
|
|
2942
|
+
/**
|
|
2943
|
+
* A retried attempt that produces output again is no longer reconnecting:
|
|
2944
|
+
* drop the retry label as soon as it streams a delta or emits a tool call, so
|
|
2945
|
+
* neither the footer status block nor the status bar keeps claiming
|
|
2946
|
+
* "重连中 N/M" for the rest of the step. The fields are only ever set by
|
|
2947
|
+
* handleStepRetrying, so this is the single clearing point besides
|
|
2948
|
+
* step/turn boundaries.
|
|
2949
|
+
*/
|
|
2950
|
+
clearReconnectState() {
|
|
2951
|
+
if (!(this.host.state.appState.reconnectAttempt > 0)) return;
|
|
2952
|
+
this.host.setAppState({
|
|
2953
|
+
reconnectAttempt: 0,
|
|
2954
|
+
reconnectMaxAttempts: void 0,
|
|
2955
|
+
reconnectDelayMs: void 0,
|
|
2956
|
+
reconnectStatusCode: void 0,
|
|
2957
|
+
reconnectErrorName: void 0
|
|
2958
|
+
});
|
|
2959
|
+
}
|
|
2939
2960
|
maybeShowDebugTiming(event) {
|
|
2940
2961
|
if (process.env["SCREAM_CODE_DEBUG"] !== "1") return;
|
|
2941
2962
|
const text = formatStepDebugTiming(event);
|
|
@@ -2995,12 +3016,14 @@ var SessionEventHandler = class {
|
|
|
2995
3016
|
}
|
|
2996
3017
|
handleThinkingDelta(event) {
|
|
2997
3018
|
const { state, streamingUI } = this.host;
|
|
3019
|
+
this.clearReconnectState();
|
|
2998
3020
|
streamingUI.appendThinkingDelta(event.delta);
|
|
2999
3021
|
if (canTransitionTo(state.appState.streamingPhase, "thinking")) this.host.setAppState({ streamingPhase: "thinking" });
|
|
3000
3022
|
streamingUI.scheduleFlush();
|
|
3001
3023
|
}
|
|
3002
3024
|
handleAssistantDelta(event) {
|
|
3003
3025
|
const { state, streamingUI } = this.host;
|
|
3026
|
+
this.clearReconnectState();
|
|
3004
3027
|
if (streamingUI.hasThinkingDraft()) streamingUI.flushThinkingToTranscript();
|
|
3005
3028
|
streamingUI.appendAssistantDelta(event.delta);
|
|
3006
3029
|
this.host.patchLivePane({
|
|
@@ -3028,6 +3051,7 @@ var SessionEventHandler = class {
|
|
|
3028
3051
|
}
|
|
3029
3052
|
handleToolCall(event) {
|
|
3030
3053
|
const { streamingUI } = this.host;
|
|
3054
|
+
this.clearReconnectState();
|
|
3031
3055
|
streamingUI.flushNow();
|
|
3032
3056
|
if (event.name === "SendSubagentMessage") {
|
|
3033
3057
|
const args = argsRecord(event.args);
|
|
@@ -3059,6 +3083,7 @@ var SessionEventHandler = class {
|
|
|
3059
3083
|
handleToolCallDelta(event) {
|
|
3060
3084
|
if (event.toolCallId.length === 0) return;
|
|
3061
3085
|
const { state, streamingUI } = this.host;
|
|
3086
|
+
this.clearReconnectState();
|
|
3062
3087
|
streamingUI.accumulateToolCallDelta(event.toolCallId, event.name, event.argumentsPart);
|
|
3063
3088
|
this.host.patchLivePane({
|
|
3064
3089
|
pendingApproval: null,
|
|
@@ -3113,7 +3138,7 @@ var SessionEventHandler = class {
|
|
|
3113
3138
|
message: event.message
|
|
3114
3139
|
};
|
|
3115
3140
|
streamingUI.completeToolResult(event.toolCallId, resultData);
|
|
3116
|
-
if (canTransitionTo(this.host.state.appState.streamingPhase, "waiting")) this.host.setAppState({ streamingPhase: "waiting" });
|
|
3141
|
+
if (!streamingUI.hasPendingToolCalls() && canTransitionTo(this.host.state.appState.streamingPhase, "waiting")) this.host.setAppState({ streamingPhase: "waiting" });
|
|
3117
3142
|
}
|
|
3118
3143
|
handleStatusUpdate(event) {
|
|
3119
3144
|
const patch = {};
|
|
@@ -3134,11 +3159,16 @@ var SessionEventHandler = class {
|
|
|
3134
3159
|
}
|
|
3135
3160
|
}
|
|
3136
3161
|
handleSessionError(event) {
|
|
3162
|
+
const hadActiveTurn = this.host.streamingUI.hasActiveTurn();
|
|
3137
3163
|
this.host.streamingUI.flushNow();
|
|
3138
3164
|
this.host.streamingUI.resetToolUi();
|
|
3139
3165
|
this.host.streamingUI.finalizeLiveTextBuffers();
|
|
3140
3166
|
this.host.streamingUI.endActivityGroup();
|
|
3141
3167
|
this.host.showError(`[${event.code}] ${event.message}`);
|
|
3168
|
+
if (event.code === "turn.agent_busy" && !hadActiveTurn && this.host.state.appState.streamingPhase !== "idle") {
|
|
3169
|
+
this.host.setAppState({ streamingPhase: "idle" });
|
|
3170
|
+
this.host.resetLivePane();
|
|
3171
|
+
}
|
|
3142
3172
|
}
|
|
3143
3173
|
handleSessionWarning(event) {
|
|
3144
3174
|
this.host.showStatus(t("handler.warning_prefix", { message: event.message }), this.host.state.theme.colors.warning);
|
|
@@ -3637,6 +3667,19 @@ var SessionEventHandler = class {
|
|
|
3637
3667
|
}
|
|
3638
3668
|
};
|
|
3639
3669
|
//#endregion
|
|
3670
|
+
//#region src/tui/utils/approval-notice.ts
|
|
3671
|
+
function buildApprovalNotice(args) {
|
|
3672
|
+
const sessionScoped = args.decision === "approved" && args.scope === "session";
|
|
3673
|
+
const tone = sessionScoped ? "approved_session" : args.decision;
|
|
3674
|
+
const label = args.decision === "approved" ? sessionScoped ? args.labels.approvedSession : args.labels.approved : args.decision === "rejected" ? args.labels.rejected : args.labels.cancelled;
|
|
3675
|
+
const feedback = args.feedback !== void 0 && args.feedback.length > 0 ? ` — "${args.feedback}"` : "";
|
|
3676
|
+
return {
|
|
3677
|
+
label,
|
|
3678
|
+
detail: `${args.action}${feedback}`,
|
|
3679
|
+
tone
|
|
3680
|
+
};
|
|
3681
|
+
}
|
|
3682
|
+
//#endregion
|
|
3640
3683
|
//#region src/tui/utils/media-url.ts
|
|
3641
3684
|
function getMediaKindLabels() {
|
|
3642
3685
|
return {
|
|
@@ -3974,6 +4017,17 @@ var SessionReplayRenderer = class {
|
|
|
3974
4017
|
this.renderApprovalResult(context, record.record);
|
|
3975
4018
|
return;
|
|
3976
4019
|
case "config_updated": return;
|
|
4020
|
+
case "stream_draft_partial": {
|
|
4021
|
+
this.flushAssistant(context);
|
|
4022
|
+
const draftText = record.text.trim();
|
|
4023
|
+
if (draftText.length > 0) collectReplayMessageContent(context.assistant, [{
|
|
4024
|
+
type: "text",
|
|
4025
|
+
text: draftText
|
|
4026
|
+
}]);
|
|
4027
|
+
this.flushAssistant(context);
|
|
4028
|
+
this.host.appendTranscriptEntry(replayEntry(context, "status", t("replay.streamDraftPartial"), "notice"));
|
|
4029
|
+
return;
|
|
4030
|
+
}
|
|
3977
4031
|
}
|
|
3978
4032
|
}
|
|
3979
4033
|
renderMessage(context, message) {
|
|
@@ -4084,6 +4138,7 @@ var SessionReplayRenderer = class {
|
|
|
4084
4138
|
}
|
|
4085
4139
|
advanceTurn(context) {
|
|
4086
4140
|
this.host.streamingUI.endActivityGroup();
|
|
4141
|
+
this.host.streamingUI.flushPendingApprovals();
|
|
4087
4142
|
context.turnIndex += 1;
|
|
4088
4143
|
context.stepIndex = 0;
|
|
4089
4144
|
context.currentTurnId = `replay:${String(context.turnIndex)}`;
|
|
@@ -4162,21 +4217,19 @@ var SessionReplayRenderer = class {
|
|
|
4162
4217
|
return;
|
|
4163
4218
|
}
|
|
4164
4219
|
const { result } = record;
|
|
4165
|
-
const
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
}
|
|
4177
|
-
|
|
4178
|
-
if (result.feedback !== void 0 && result.feedback.length > 0) parts.push(` — "${result.feedback}"`);
|
|
4179
|
-
this.host.appendTranscriptEntry(replayEntry(context, "status", parts.join(""), "notice"));
|
|
4220
|
+
const notice = buildApprovalNotice({
|
|
4221
|
+
decision: result.decision,
|
|
4222
|
+
scope: result.scope,
|
|
4223
|
+
action: record.action,
|
|
4224
|
+
feedback: result.feedback,
|
|
4225
|
+
labels: {
|
|
4226
|
+
approved: t("replay.approved"),
|
|
4227
|
+
approvedSession: t("replay.approved_session"),
|
|
4228
|
+
rejected: t("replay.rejected"),
|
|
4229
|
+
cancelled: t("replay.cancelled")
|
|
4230
|
+
}
|
|
4231
|
+
});
|
|
4232
|
+
this.host.streamingUI.recordApproval(record.toolCallId, notice.label, notice.detail, notice.tone);
|
|
4180
4233
|
}
|
|
4181
4234
|
renderPlanReviewResult(context, record) {
|
|
4182
4235
|
const { result } = record;
|
|
@@ -4355,6 +4408,11 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4355
4408
|
_pendingToolComponents = /* @__PURE__ */ new Map();
|
|
4356
4409
|
_pendingAgentGroup = null;
|
|
4357
4410
|
_activityGroup;
|
|
4411
|
+
/**
|
|
4412
|
+
* Approval outcomes answered before their tool call was dispatched, waiting
|
|
4413
|
+
* for the call's row to appear (see `recordApproval`). Keyed by call id.
|
|
4414
|
+
*/
|
|
4415
|
+
_pendingApprovals = /* @__PURE__ */ new Map();
|
|
4358
4416
|
/** Guards the single `registerLiveComponent` call for the turn's block. */
|
|
4359
4417
|
_activityGroupRegistered = false;
|
|
4360
4418
|
/** Block that borrowed a card, so late results refresh their own block. */
|
|
@@ -4567,6 +4625,19 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4567
4625
|
this._streamingToolCallArguments.delete(toolCallId);
|
|
4568
4626
|
return matchedCall;
|
|
4569
4627
|
}
|
|
4628
|
+
/** True while a tool call of the step being handled has no result yet. A
|
|
4629
|
+
* parallel batch dispatches its results in provider order, so this is what
|
|
4630
|
+
* keeps the footer in "执行中" until the whole batch settles instead of
|
|
4631
|
+
* flipping to "等待中" on the first result. Entries from an earlier step or
|
|
4632
|
+
* turn are ignored: nothing can settle them any more, and counting them
|
|
4633
|
+
* would pin the footer in "执行中" for the rest of the turn. */
|
|
4634
|
+
hasPendingToolCalls() {
|
|
4635
|
+
for (const call of this._activeToolCalls.values()) {
|
|
4636
|
+
if (call.turnId !== this._currentTurnId || call.step !== this._currentStep) continue;
|
|
4637
|
+
if (call.result === void 0) return true;
|
|
4638
|
+
}
|
|
4639
|
+
return false;
|
|
4640
|
+
}
|
|
4570
4641
|
/** Marks in-flight tool calls as truncated when a step hits max_tokens.
|
|
4571
4642
|
* Returns the count of tool calls that were truncated. */
|
|
4572
4643
|
markStepTruncated(turnId, step) {
|
|
@@ -4587,6 +4658,7 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4587
4658
|
/** Tears down replay-specific state after session history has been rendered. */
|
|
4588
4659
|
cleanupAfterReplay(completedToolCallIds) {
|
|
4589
4660
|
this.endActivityGroup();
|
|
4661
|
+
this.flushPendingApprovals();
|
|
4590
4662
|
this._activeToolCalls.clear();
|
|
4591
4663
|
for (const toolCallId of completedToolCallIds) this._pendingToolComponents.delete(toolCallId);
|
|
4592
4664
|
this._pendingAgentGroup = null;
|
|
@@ -4654,6 +4726,65 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4654
4726
|
group.attachNotice(data);
|
|
4655
4727
|
return true;
|
|
4656
4728
|
}
|
|
4729
|
+
/**
|
|
4730
|
+
* Files an approval outcome with the call it allowed.
|
|
4731
|
+
*
|
|
4732
|
+
* The prompt is answered before its tool call is dispatched, so the row it
|
|
4733
|
+
* belongs under usually does not exist yet: while a turn is running the
|
|
4734
|
+
* outcome waits here for its own call to appear, and is filed under it the
|
|
4735
|
+
* moment it does. Two cases keep the row they always had instead — an outcome
|
|
4736
|
+
* answered between turns (a background agent's call, where no block will ever
|
|
4737
|
+
* open), and one whose call's row is not in the block that is open now (a
|
|
4738
|
+
* subagent's call, a card that stays standalone, a block that already
|
|
4739
|
+
* settled), which is mounted when the step settles.
|
|
4740
|
+
*/
|
|
4741
|
+
recordApproval(callId, label, detail, tone) {
|
|
4742
|
+
const card = this._pendingToolComponents.get(callId);
|
|
4743
|
+
const owner = card === void 0 ? void 0 : this._groupByToolCard.get(card);
|
|
4744
|
+
if (owner !== void 0 && this.host.state.transcriptContainer.children.includes(owner) && owner.attachApproval(callId, label, detail, tone)) return;
|
|
4745
|
+
const group = this._activityGroup;
|
|
4746
|
+
if (group !== void 0 && group.attachApproval(callId, label, detail, tone)) return;
|
|
4747
|
+
if (!this.hasActiveTurn()) {
|
|
4748
|
+
this.mountApprovalNotices([{
|
|
4749
|
+
label,
|
|
4750
|
+
detail,
|
|
4751
|
+
tone
|
|
4752
|
+
}]);
|
|
4753
|
+
return;
|
|
4754
|
+
}
|
|
4755
|
+
this._pendingApprovals.set(callId, {
|
|
4756
|
+
label,
|
|
4757
|
+
detail,
|
|
4758
|
+
tone
|
|
4759
|
+
});
|
|
4760
|
+
}
|
|
4761
|
+
/** Files the outcome waiting for this call, now that its row exists. */
|
|
4762
|
+
adoptPendingApproval(group, callId) {
|
|
4763
|
+
const pending = this._pendingApprovals.get(callId);
|
|
4764
|
+
if (pending === void 0) return;
|
|
4765
|
+
this._pendingApprovals.delete(callId);
|
|
4766
|
+
if (!group.attachApproval(callId, pending.label, pending.detail, pending.tone)) this.mountApprovalNotices([pending]);
|
|
4767
|
+
}
|
|
4768
|
+
/**
|
|
4769
|
+
* Mounts outcomes as their own notice row — the row an approval used to get
|
|
4770
|
+
* straight away, and the fallback for anything no block ever claims.
|
|
4771
|
+
*/
|
|
4772
|
+
mountApprovalNotices(approvals) {
|
|
4773
|
+
for (const approval of approvals) this.host.transcriptController.appendEntry({
|
|
4774
|
+
id: nextTranscriptId(),
|
|
4775
|
+
kind: "status",
|
|
4776
|
+
renderMode: "notice",
|
|
4777
|
+
content: `${approval.label}: ${approval.detail}`
|
|
4778
|
+
});
|
|
4779
|
+
this.host.state.ui.requestRender();
|
|
4780
|
+
}
|
|
4781
|
+
/** Settles anything still waiting: mounted as notices, in the order answered. */
|
|
4782
|
+
flushPendingApprovals() {
|
|
4783
|
+
if (this._pendingApprovals.size === 0) return;
|
|
4784
|
+
const parked = [...this._pendingApprovals.values()];
|
|
4785
|
+
this._pendingApprovals.clear();
|
|
4786
|
+
this.mountApprovalNotices(parked);
|
|
4787
|
+
}
|
|
4657
4788
|
endActivityGroup() {
|
|
4658
4789
|
const group = this._activityGroup;
|
|
4659
4790
|
this._activityGroup = void 0;
|
|
@@ -4788,6 +4919,7 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4788
4919
|
this._streamingToolCallArguments.clear();
|
|
4789
4920
|
this.disposeAndClearPendingToolComponents();
|
|
4790
4921
|
this._pendingAgentGroup = null;
|
|
4922
|
+
this.flushPendingApprovals();
|
|
4791
4923
|
}
|
|
4792
4924
|
resetToolCallState() {
|
|
4793
4925
|
this._activeToolCalls.clear();
|
|
@@ -4951,6 +5083,7 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4951
5083
|
if (state.planExpanded) tc.setPlanExpanded(true);
|
|
4952
5084
|
if (toolCall.name !== "Agent") this._pendingAgentGroup = null;
|
|
4953
5085
|
if (!this.tryAttachAgentToolCall(toolCall, tc)) if (StreamingUIController.STANDALONE_TOOL_NAMES.has(toolCall.name)) {
|
|
5086
|
+
if (toolCall.name === "ExitPlanMode") this.endActivityGroup();
|
|
4954
5087
|
tc.setExpanded(state.toolOutputExpanded);
|
|
4955
5088
|
state.transcriptContainer.addChild(tc);
|
|
4956
5089
|
state.ui.requestRender();
|
|
@@ -4958,7 +5091,8 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4958
5091
|
const group = this.ensureActivityGroup();
|
|
4959
5092
|
this.registerActivityGroupEntry(group, entry);
|
|
4960
5093
|
this._groupByToolCard.set(tc, group);
|
|
4961
|
-
group.attachTool(tc, toolCall.step ?? this._currentStep);
|
|
5094
|
+
group.attachTool(tc, toolCall.step ?? this._currentStep, toolCall.id);
|
|
5095
|
+
this.adoptPendingApproval(group, toolCall.id);
|
|
4962
5096
|
state.ui.requestRender();
|
|
4963
5097
|
}
|
|
4964
5098
|
if (toolCall.name === "ExitPlanMode" && typeof toolCall.args["plan"] !== "string") {
|
|
@@ -6270,6 +6404,9 @@ var TranscriptController = class TranscriptController {
|
|
|
6270
6404
|
welcomeComponent;
|
|
6271
6405
|
committedComponent;
|
|
6272
6406
|
liveComponentToEntry = /* @__PURE__ */ new Map();
|
|
6407
|
+
/** Live `started` notice cards by task id, so the terminal notice can stop the
|
|
6408
|
+
* ticker of the card that is still claiming the task is running. */
|
|
6409
|
+
liveNoticesByTrackingId = /* @__PURE__ */ new Map();
|
|
6273
6410
|
pendingComponents = /* @__PURE__ */ new Set();
|
|
6274
6411
|
/** Max live transcript children before the oldest are folded into the
|
|
6275
6412
|
* committed single-line summary. Overridable via SCREAM_TRANSCRIPT_LIVE_LIMIT
|
|
@@ -6295,6 +6432,26 @@ var TranscriptController = class TranscriptController {
|
|
|
6295
6432
|
releaseLiveComponent(component) {
|
|
6296
6433
|
this.liveComponentToEntry.delete(component);
|
|
6297
6434
|
}
|
|
6435
|
+
/**
|
|
6436
|
+
* Stop everything a component owns once it leaves the live area. Committed
|
|
6437
|
+
* views re-render from the entry data, so disposing cannot lose content, but
|
|
6438
|
+
* skipping it would let an animation timer outlive the row it belonged to.
|
|
6439
|
+
*/
|
|
6440
|
+
dropLiveComponent(component) {
|
|
6441
|
+
for (const [trackingId, tracked] of this.liveNoticesByTrackingId) if (tracked === component) this.liveNoticesByTrackingId.delete(trackingId);
|
|
6442
|
+
if (hasDispose(component)) component.dispose();
|
|
6443
|
+
}
|
|
6444
|
+
/**
|
|
6445
|
+
* Stops the ticker of the card that announced `trackingId`. Called when the
|
|
6446
|
+
* task reaches a terminal state: that card is history now, and a glyph that
|
|
6447
|
+
* keeps rotating would claim the task is still running.
|
|
6448
|
+
*/
|
|
6449
|
+
settleLiveNotice(trackingId) {
|
|
6450
|
+
const tracked = this.liveNoticesByTrackingId.get(trackingId);
|
|
6451
|
+
if (tracked === void 0) return;
|
|
6452
|
+
this.liveNoticesByTrackingId.delete(trackingId);
|
|
6453
|
+
tracked.settle();
|
|
6454
|
+
}
|
|
6298
6455
|
markPending(component) {
|
|
6299
6456
|
this.pendingComponents.add(component);
|
|
6300
6457
|
}
|
|
@@ -6336,6 +6493,7 @@ var TranscriptController = class TranscriptController {
|
|
|
6336
6493
|
this.committedComponent.appendEntry(entry, state.theme.colors);
|
|
6337
6494
|
container.removeChild(component);
|
|
6338
6495
|
this.liveComponentToEntry.delete(component);
|
|
6496
|
+
this.dropLiveComponent(component);
|
|
6339
6497
|
}
|
|
6340
6498
|
this.committedComponent.setCount(this.committedComponent.getCount() + toCommit.length);
|
|
6341
6499
|
if (process.env["SCREAM_CODE_DEBUG"] === "1") this.host.showStatus(`[debug] committed=${this.committedComponent.getCount()} live=${this.getLiveCount()}`);
|
|
@@ -6370,10 +6528,10 @@ var TranscriptController = class TranscriptController {
|
|
|
6370
6528
|
if (state.planExpanded) tc.setPlanExpanded(true);
|
|
6371
6529
|
return tc;
|
|
6372
6530
|
}
|
|
6373
|
-
if (entry.backgroundAgentStatus !== void 0) return new BackgroundAgentStatusComponent(entry.backgroundAgentStatus, state.theme.colors);
|
|
6531
|
+
if (entry.backgroundAgentStatus !== void 0) return new BackgroundAgentStatusComponent(entry.backgroundAgentStatus, state.theme.colors, state.ui);
|
|
6374
6532
|
return entry.renderMode === "notice" ? new NoticeMessageComponent(entry.content, entry.detail, state.theme.colors, entry.noticeMarkerColor) : new StatusMessageComponent(entry.content, state.theme.colors, entry.color);
|
|
6375
6533
|
case "status":
|
|
6376
|
-
if (entry.backgroundAgentStatus !== void 0) return new BackgroundAgentStatusComponent(entry.backgroundAgentStatus, state.theme.colors);
|
|
6534
|
+
if (entry.backgroundAgentStatus !== void 0) return new BackgroundAgentStatusComponent(entry.backgroundAgentStatus, state.theme.colors, state.ui);
|
|
6377
6535
|
return entry.renderMode === "notice" ? new NoticeMessageComponent(entry.content, entry.detail, state.theme.colors, entry.noticeMarkerColor) : new StatusMessageComponent(entry.content, state.theme.colors, entry.color);
|
|
6378
6536
|
case "cron":
|
|
6379
6537
|
if (entry.cronData === void 0) return null;
|
|
@@ -6388,8 +6546,15 @@ var TranscriptController = class TranscriptController {
|
|
|
6388
6546
|
if (component) {
|
|
6389
6547
|
this.liveComponentToEntry.set(component, entry);
|
|
6390
6548
|
const status = entry.backgroundAgentStatus;
|
|
6391
|
-
if (status !== void 0 &&
|
|
6392
|
-
|
|
6549
|
+
if (status !== void 0 && component instanceof BackgroundAgentStatusComponent) {
|
|
6550
|
+
const trackingId = status.trackingId;
|
|
6551
|
+
if (trackingId !== void 0) if (status.phase === "started") this.liveNoticesByTrackingId.set(trackingId, component);
|
|
6552
|
+
else this.settleLiveNotice(trackingId);
|
|
6553
|
+
}
|
|
6554
|
+
if (status !== void 0 && this.host.streamingUI.attachNotice(status)) {
|
|
6555
|
+
this.releaseLiveComponent(component);
|
|
6556
|
+
this.dropLiveComponent(component);
|
|
6557
|
+
} else this.host.state.transcriptContainer.addChild(component);
|
|
6393
6558
|
this.host.state.ui.requestRender();
|
|
6394
6559
|
}
|
|
6395
6560
|
return component ?? null;
|
|
@@ -6415,26 +6580,19 @@ var TranscriptController = class TranscriptController {
|
|
|
6415
6580
|
}
|
|
6416
6581
|
appendApprovalEntry(request, response) {
|
|
6417
6582
|
if (request.toolName === "ExitPlanMode" || request.display.kind === "plan_review") return;
|
|
6418
|
-
const
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
|
|
6425
|
-
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
|
|
6429
|
-
}
|
|
6430
|
-
parts.push(`: ${request.action}`);
|
|
6431
|
-
if (response.feedback !== void 0 && response.feedback.length > 0) parts.push(` — "${response.feedback}"`);
|
|
6432
|
-
this.appendEntry({
|
|
6433
|
-
id: nextTranscriptId(),
|
|
6434
|
-
kind: "status",
|
|
6435
|
-
renderMode: "notice",
|
|
6436
|
-
content: parts.join("")
|
|
6583
|
+
const notice = buildApprovalNotice({
|
|
6584
|
+
decision: response.decision,
|
|
6585
|
+
scope: response.scope,
|
|
6586
|
+
action: request.action,
|
|
6587
|
+
feedback: response.feedback,
|
|
6588
|
+
labels: {
|
|
6589
|
+
approved: t("tc.approved"),
|
|
6590
|
+
approvedSession: t("tc.approved_session"),
|
|
6591
|
+
rejected: t("tc.rejected"),
|
|
6592
|
+
cancelled: t("tc.cancelled")
|
|
6593
|
+
}
|
|
6437
6594
|
});
|
|
6595
|
+
this.host.streamingUI.recordApproval(request.toolCallId, notice.label, notice.detail, notice.tone);
|
|
6438
6596
|
}
|
|
6439
6597
|
renderWelcome() {
|
|
6440
6598
|
const { state } = this.host;
|
|
@@ -6453,6 +6611,7 @@ var TranscriptController = class TranscriptController {
|
|
|
6453
6611
|
const { state, streamingUI, imageStore } = this.host;
|
|
6454
6612
|
streamingUI.discardPending();
|
|
6455
6613
|
streamingUI.endActivityGroup();
|
|
6614
|
+
streamingUI.flushPendingApprovals();
|
|
6456
6615
|
state.transcriptEntries = [];
|
|
6457
6616
|
streamingUI.disposeActiveCompactionBlock();
|
|
6458
6617
|
streamingUI.resetLiveText();
|
|
@@ -13362,6 +13521,7 @@ function createInitialAppState(input) {
|
|
|
13362
13521
|
isSwitchingSession: false,
|
|
13363
13522
|
streamingPhase: "idle",
|
|
13364
13523
|
streamingStartTime: 0,
|
|
13524
|
+
pendingUserAction: null,
|
|
13365
13525
|
theme: input.tuiConfig.theme,
|
|
13366
13526
|
version: input.version,
|
|
13367
13527
|
hasNewVersion: false,
|
|
@@ -13798,14 +13958,28 @@ var ScreamTUI = class {
|
|
|
13798
13958
|
patchLivePane(patch) {
|
|
13799
13959
|
if (!hasPatchChanges(this.state.livePane, patch)) return;
|
|
13800
13960
|
Object.assign(this.state.livePane, patch);
|
|
13961
|
+
this.syncPendingUserAction();
|
|
13801
13962
|
this.lifecycleController.updateActivityPane();
|
|
13802
13963
|
this.state.ui.requestRender();
|
|
13803
13964
|
}
|
|
13804
13965
|
resetLivePane() {
|
|
13805
13966
|
this.state.livePane = { ...INITIAL_LIVE_PANE };
|
|
13967
|
+
this.syncPendingUserAction();
|
|
13806
13968
|
this.lifecycleController.updateActivityPane();
|
|
13807
13969
|
this.state.ui.requestRender();
|
|
13808
13970
|
}
|
|
13971
|
+
/**
|
|
13972
|
+
* Mirror the live pane's pending panels onto `AppState.pendingUserAction` so
|
|
13973
|
+
* the footer status block can report "等待批准/等待回答" instead of claiming a
|
|
13974
|
+
* running phase while a panel is blocked on the user. Every mutation of
|
|
13975
|
+
* `livePane` goes through patchLivePane/resetLivePane, so this stays the
|
|
13976
|
+
* single writer of that field.
|
|
13977
|
+
*/
|
|
13978
|
+
syncPendingUserAction() {
|
|
13979
|
+
const { pendingApproval, pendingQuestion } = this.state.livePane;
|
|
13980
|
+
const next = pendingApproval !== null ? "approval" : pendingQuestion !== null ? "question" : null;
|
|
13981
|
+
if (next !== this.state.appState.pendingUserAction) this.setAppState({ pendingUserAction: next });
|
|
13982
|
+
}
|
|
13809
13983
|
requireSession() {
|
|
13810
13984
|
if (this.session === void 0) throw new Error(getNoActiveSessionMessage());
|
|
13811
13985
|
return this.session;
|
|
@@ -13882,7 +14056,7 @@ var ScreamTUI = class {
|
|
|
13882
14056
|
const card = new OnboardingCardComponent({
|
|
13883
14057
|
colors: this.state.theme.colors,
|
|
13884
14058
|
onConfigure: () => {
|
|
13885
|
-
import("./dispatch-
|
|
14059
|
+
import("./dispatch-dDbUBD7J.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
|
|
13886
14060
|
this.restoreEditor();
|
|
13887
14061
|
onDone?.();
|
|
13888
14062
|
});
|
|
@@ -13903,7 +14077,7 @@ var ScreamTUI = class {
|
|
|
13903
14077
|
if (this.state.startupState === "picker") return;
|
|
13904
14078
|
try {
|
|
13905
14079
|
await getKnowledgeStore();
|
|
13906
|
-
if (
|
|
14080
|
+
if (hasEmbeddingModelCache()) {
|
|
13907
14081
|
startManualEmbeddingDownload().catch(() => {});
|
|
13908
14082
|
return;
|
|
13909
14083
|
}
|
|
@@ -13918,8 +14092,9 @@ var ScreamTUI = class {
|
|
|
13918
14092
|
const spinner = this.showProgressSpinner(t("kw.embedding_downloading"));
|
|
13919
14093
|
let ok = false;
|
|
13920
14094
|
let error;
|
|
14095
|
+
let failureKind;
|
|
13921
14096
|
try {
|
|
13922
|
-
({ok, error} = await startManualEmbeddingDownload());
|
|
14097
|
+
({ok, error, failureKind} = await startManualEmbeddingDownload());
|
|
13923
14098
|
} catch (error) {
|
|
13924
14099
|
error = error instanceof Error ? error.message : String(error);
|
|
13925
14100
|
}
|
|
@@ -13929,7 +14104,7 @@ var ScreamTUI = class {
|
|
|
13929
14104
|
});
|
|
13930
14105
|
if (ok) this.showStatus(t("kw.embedding_ready"));
|
|
13931
14106
|
else {
|
|
13932
|
-
const detail =
|
|
14107
|
+
const detail = embeddingFailureDetail(failureKind, error);
|
|
13933
14108
|
this.showNotice(t("kw.embedding_failed"), detail);
|
|
13934
14109
|
}
|
|
13935
14110
|
})();
|
|
@@ -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 { nn as handleConnectCommand } from "./dispatch-
|
|
6
|
+
import { nn as handleConnectCommand } from "./dispatch-fjwbqaYI.mjs";
|
|
7
7
|
export { handleConnectCommand };
|