scream-code 0.16.7 → 0.16.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/dist/{app-DDepBvBx.mjs → app-GeQQHNLx.mjs} +93 -14
- package/dist/{dispatch-Vw9ccFm7.mjs → dispatch-CNitkOqX.mjs} +346 -1870
- package/dist/{dispatch-CIGyjBDa.mjs → dispatch-Du8ddILK.mjs} +1 -1
- package/dist/main.mjs +1 -1
- package/dist/src-CXmZg1VT.mjs +4115 -0
- package/dist/{src-h6ZExh4A.mjs → src-DIAKpkXO.mjs} +1 -1
- package/dist/{text-input-dialog-D9ByqSsK.mjs → text-input-dialog-6v2667rm.mjs} +6 -2
- package/dist/{text-input-dialog-B-6Pgo6m.mjs → text-input-dialog-DDUarM0_.mjs} +1 -1
- package/package.json +1 -1
- package/dist/src-tDEINaMV.mjs +0 -2249
|
@@ -4,8 +4,9 @@ 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 {
|
|
8
|
-
import { a as
|
|
7
|
+
import { k as MemoryMemoStore } from "./src-CXmZg1VT.mjs";
|
|
8
|
+
import { $n as encodeWorkDirKey, $t as lerpGradient, A as highlightLines, An as embeddingFailureDetail, At as isTurnElapsedEnabled, B as ActivityGroupComponent, Bn as detectShellEnvironment, Bt as ENABLE_TERMINAL_THEME_REPORTING, Cn as getLlmNotSetMessage, Ct as clearInfoPanelState, D as ToolCallComponent, Dn as sortSlashCommands, Dt as createEditorTheme, E as UserMessageComponent, En as BUILTIN_SLASH_COMMANDS, Et as resolveThemeSync, F as StatusMessageComponent, Fn as PULSE_WAVE_FRAMES, Ft as detectTerminalTheme, G as AgentGroupComponent, Gn as CLI_COMMAND_NAME, Gt as QUERY_TERMINAL_THEME, H as estimateTokens, Hn as getInputHistoryFile, Ht as OSC11_RESPONSE, I as replaceTabs, In as TuiConfigParseError, It as parseOsc11BackgroundTheme, J as getBreathingFrame, Jn as PRODUCT_NAME, Jt as TERMINAL_THEME_DARK, K as WelcomeComponent, Kn as CLI_UI_MODE, Kt as TERMINAL_FOCUS_IN, L as sanitizeShellOutput, Ln as TuiLikePreferencesSchema, Lt as DISABLE_TERMINAL_FOCUS_REPORTING, M as CachedContainer, Mn as hasEmbeddingModelCache, Mt as createThemeStyles, N as ThinkingComponent, Nn as startManualEmbeddingDownload, Nt as contrastTextHex, O as renderDiffLines, On as isExperimentalFlagEnabled, Ot as createMarkdownTheme, P as NoticeMessageComponent, Pn as PIXEL_PULSE_FRAMES, Pt as getColorPalette, Q as refineGoal, Qn as ScreamHarness, Qt as FooterComponent, R as SkillActivationComponent, Rn as loadTuiConfig, Rt as DISABLE_TERMINAL_THEME_REPORTING, S as readJsonlFile, Sn as getCtrlDHint, St as supportsBalance, Tn as buildSkillSlashCommands, U as getSharedSpeedTracker, Un as getLogDir, Ut as OSC11_RESPONSE_PREFIX, V as charsForTokenBudget, Vn as getDataDir, Vt as OSC11_QUERY, W as BackgroundAgentStatusComponent, Wn as detectInstallSource, Wt as OSC11_RESPONSE_PREFIX_NO_ESC, X as CompactionComponent, Xn as fetchCatalog, Xt as isBusy, Y as resetBreathingClock, Yn as DEFAULT_CATALOG_URL, Yt as TERMINAL_THEME_LIGHT, Z as clearGoalState, Zn as saveCatalogCache, Zt as isStreaming, _n as EXIT_CONFIRM_WINDOW_MS, a as syncDiagramCapabilityPrompt, an as printableChar, ar as resolveScreamHome, at as toTerminalHyperlink, b as readUpdateCache, bn as TIP_ROTATION_INTERVAL_MS, c as disposeChildren, cn as appendStreamingArgsPreview, cr as resolveGlobalLogPath, d as isPlanExpandable, dn as isTodoItemShape, dr as ErrorCodes, en as SubagentSlots, er as normalizeWorkDir, f as MoonLoader, fn as parseStreamingArgs, fr as SCREAM_ERROR_INFO, ft as handleFusionPlanCommand, gn as EMPTY_SESSION_HINT_URL, hn as truncateErrorMessage, i as buildRoleAdditionalText, it as isInternalMessage, j as langFromPath, jn as getKnowledgeStore, jt as toggleEmptySessionHint, k as renderDiffLinesClustered, kn as setExperimentalFlags, kt as isEmptySessionHintDismissed, l as hasDispose, ln as argsRecord, lr as isScreamError, mn as stringValue, mt as handlePlanCommand, n as clearEvalPanelState, nr as readSessionIndex, on as STATUS_BULLET, or as flushDiagnosticLogs, ot as changeThinkingLevel, p as formatMemoryMemoForInjection, pn as serializeToolResultOutput, q as BREATHE_CYCLE_MS, qn as CLI_USER_AGENT_PRODUCT, qt as TERMINAL_FOCUS_OUT, r as openUrl, rr as removeSessionIndexEntry, sn as appendSessionHeaderHint, sr as log, st as getModelCycleLevel, t as dispatchInput, tr as appendSessionIndexEntry, u as isExpandable, un as formatErrorMessage, ur as isOrphanedToolCallError, v as selectUpdateTarget, vn as MAIN_AGENT_ID, w as getDaemonInstructions, wn as getNoActiveSessionMessage, x as appendJsonlLine, xn as getCtrlCHint, xt as refreshProviderBalance, y as refreshUpdateCache, yn as SESSION_TIPS, z as AssistantMessageComponent, zn as saveTuiConfig, zt as ENABLE_TERMINAL_FOCUS_REPORTING } from "./dispatch-CNitkOqX.mjs";
|
|
9
|
+
import { a as setLocale, i as getLocale, o as t } from "./text-input-dialog-6v2667rm.mjs";
|
|
9
10
|
import { createRequire } from "node:module";
|
|
10
11
|
import { randomBytes, randomUUID, scryptSync, timingSafeEqual } from "node:crypto";
|
|
11
12
|
import { access, appendFile, chmod, mkdir, mkdtemp, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
@@ -32,7 +33,7 @@ function optionalBuildString(value) {
|
|
|
32
33
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
33
34
|
}
|
|
34
35
|
const SCREAM_BUILD_INFO = {
|
|
35
|
-
version: optionalBuildString("0.16.
|
|
36
|
+
version: optionalBuildString("0.16.8"),
|
|
36
37
|
channel: optionalBuildString(""),
|
|
37
38
|
commit: optionalBuildString(""),
|
|
38
39
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -1877,7 +1878,7 @@ var EditorKeyboardController = class {
|
|
|
1877
1878
|
if (media === null) return;
|
|
1878
1879
|
const meta = parseImageMeta(media.bytes);
|
|
1879
1880
|
if (meta === null) return;
|
|
1880
|
-
const attachment = this.imageStore.addImage(media.bytes, meta.mime, meta.width, meta.height);
|
|
1881
|
+
const attachment = this.imageStore.addImage(media.bytes, meta.mime, meta.width, meta.height, path);
|
|
1881
1882
|
this.host.state.editor.insertTextAtCursor?.(`${attachment.placeholder} `);
|
|
1882
1883
|
this.host.state.ui.requestRender();
|
|
1883
1884
|
}
|
|
@@ -3164,7 +3165,8 @@ var SessionEventHandler = class {
|
|
|
3164
3165
|
this.host.streamingUI.resetToolUi();
|
|
3165
3166
|
this.host.streamingUI.finalizeLiveTextBuffers();
|
|
3166
3167
|
this.host.streamingUI.endActivityGroup();
|
|
3167
|
-
|
|
3168
|
+
const shown = appendSessionHeaderHint(`[${event.code}] ${event.message}`, (name) => t("error.session_header_hint", { name }));
|
|
3169
|
+
this.host.showError(shown);
|
|
3168
3170
|
if (event.code === "turn.agent_busy" && !hadActiveTurn && this.host.state.appState.streamingPhase !== "idle") {
|
|
3169
3171
|
this.host.setAppState({ streamingPhase: "idle" });
|
|
3170
3172
|
this.host.resetLivePane();
|
|
@@ -4621,6 +4623,7 @@ var StreamingUIController = class StreamingUIController {
|
|
|
4621
4623
|
completeToolResult(toolCallId, result) {
|
|
4622
4624
|
const matchedCall = this._activeToolCalls.get(toolCallId);
|
|
4623
4625
|
if (matchedCall !== void 0) this.onToolCallEnd(toolCallId, result);
|
|
4626
|
+
else if (this._pendingToolComponents.has(toolCallId)) this.onToolCallEnd(toolCallId, result);
|
|
4624
4627
|
this._activeToolCalls.delete(toolCallId);
|
|
4625
4628
|
this._streamingToolCallArguments.delete(toolCallId);
|
|
4626
4629
|
return matchedCall;
|
|
@@ -6246,10 +6249,28 @@ function cronDetail(data) {
|
|
|
6246
6249
|
}
|
|
6247
6250
|
//#endregion
|
|
6248
6251
|
//#region src/tui/utils/image-attachment-store.ts
|
|
6252
|
+
/**
|
|
6253
|
+
* Registry for media pasted into the input box.
|
|
6254
|
+
*
|
|
6255
|
+
* Each paste produces an `ImageAttachment` with an auto-incrementing id
|
|
6256
|
+
* or `VideoAttachment` with a human-readable placeholder (`[image #1
|
|
6257
|
+
* (640×480)]` / `[video #2 sample.mov]`). The placeholder is what the
|
|
6258
|
+
* user sees in the input field; on submit, `extractMediaAttachments`
|
|
6259
|
+
* walks the text and expands image placeholders to image content parts
|
|
6260
|
+
* and video placeholders to file-path tags for `ReadMediaFile`.
|
|
6261
|
+
*
|
|
6262
|
+
* Scope is per-`ScreamTUI` instance. Reloads (`/new`, `/clear`,
|
|
6263
|
+
* session switch) call `clear()` so ids restart from 1 and stale
|
|
6264
|
+
* prompt attachments are dropped. We intentionally do NOT persist
|
|
6265
|
+
* attachments across sessions — coding-agent doesn't either, and
|
|
6266
|
+
* `--resume` wouldn't know how to materialize the files anyway.
|
|
6267
|
+
*/
|
|
6268
|
+
/** Temp-file basename prefix used by path-mode image materialization. */
|
|
6269
|
+
const TEMP_ATTACHMENT_PREFIX = "scream-attachment-";
|
|
6249
6270
|
var ImageAttachmentStore = class {
|
|
6250
6271
|
nextId = 1;
|
|
6251
6272
|
byId = /* @__PURE__ */ new Map();
|
|
6252
|
-
addImage(bytes, mime, width, height) {
|
|
6273
|
+
addImage(bytes, mime, width, height, sourcePath) {
|
|
6253
6274
|
const id = this.nextId;
|
|
6254
6275
|
this.nextId += 1;
|
|
6255
6276
|
const attachment = {
|
|
@@ -6259,7 +6280,8 @@ var ImageAttachmentStore = class {
|
|
|
6259
6280
|
mime,
|
|
6260
6281
|
width,
|
|
6261
6282
|
height,
|
|
6262
|
-
placeholder: formatPlaceholder(id, width, height)
|
|
6283
|
+
placeholder: formatPlaceholder(id, width, height),
|
|
6284
|
+
...sourcePath !== void 0 && sourcePath.length > 0 ? { sourcePath } : {}
|
|
6263
6285
|
};
|
|
6264
6286
|
this.byId.set(id, attachment);
|
|
6265
6287
|
return attachment;
|
|
@@ -6285,6 +6307,14 @@ var ImageAttachmentStore = class {
|
|
|
6285
6307
|
return this.byId.get(id);
|
|
6286
6308
|
}
|
|
6287
6309
|
clear() {
|
|
6310
|
+
const tempBase = join(tmpdir(), TEMP_ATTACHMENT_PREFIX);
|
|
6311
|
+
for (const attachment of this.byId.values()) {
|
|
6312
|
+
if (attachment.kind !== "image") continue;
|
|
6313
|
+
const path = attachment.sourcePath;
|
|
6314
|
+
if (path !== void 0 && path.startsWith(tempBase)) try {
|
|
6315
|
+
unlinkSync(path);
|
|
6316
|
+
} catch {}
|
|
6317
|
+
}
|
|
6288
6318
|
this.byId.clear();
|
|
6289
6319
|
this.nextId = 1;
|
|
6290
6320
|
}
|
|
@@ -8688,8 +8718,25 @@ var QueuePaneComponent = class extends Container {
|
|
|
8688
8718
|
};
|
|
8689
8719
|
//#endregion
|
|
8690
8720
|
//#region src/tui/utils/image-placeholder.ts
|
|
8721
|
+
/**
|
|
8722
|
+
* Scan submitted text for media placeholders and produce
|
|
8723
|
+
* the `PromptPart[]` we'll send to the SDK prompt endpoint.
|
|
8724
|
+
*
|
|
8725
|
+
* Rules:
|
|
8726
|
+
* - Only placeholders that resolve against `store` get extracted.
|
|
8727
|
+
* A literal `[image #999 ...]` the user typed themselves stays in
|
|
8728
|
+
* the text (we can't hallucinate files for it).
|
|
8729
|
+
* - Order is preserved for text/image/video segments. Image placeholders
|
|
8730
|
+
* expand to image content parts so the prompt reaches the provider
|
|
8731
|
+
* without relying on a model tool call. Video placeholders still expand
|
|
8732
|
+
* to file-path tags so `ReadMediaFile` can own video upload behavior.
|
|
8733
|
+
* - Adjacent text segments are flattened — empty / whitespace-only
|
|
8734
|
+
* segments drop out so we never emit `{type:'text', text:' '}`
|
|
8735
|
+
* noise between two media parts.
|
|
8736
|
+
*/
|
|
8691
8737
|
const PLACEHOLDER_REGEX = /\[(image|video) #(\d+) (?:(\(\d+×\d+\))|([^\]]+))\]/g;
|
|
8692
|
-
function extractMediaAttachments(text, store) {
|
|
8738
|
+
function extractMediaAttachments(text, store, options = {}) {
|
|
8739
|
+
const imageMode = options.imageMode ?? "inline";
|
|
8693
8740
|
const parts = [];
|
|
8694
8741
|
const imageAttachmentIds = [];
|
|
8695
8742
|
const videoAttachmentIds = [];
|
|
@@ -8709,6 +8756,13 @@ function extractMediaAttachments(text, store) {
|
|
|
8709
8756
|
if (attachment.kind === "video") {
|
|
8710
8757
|
pushText(parts, tagTextForVideo(attachment));
|
|
8711
8758
|
videoAttachmentIds.push(id);
|
|
8759
|
+
} else if (imageMode === "path") {
|
|
8760
|
+
try {
|
|
8761
|
+
pushText(parts, formatMediaTag("image", ensureImagePath(attachment)));
|
|
8762
|
+
} catch {
|
|
8763
|
+
parts.push(imagePartForAttachment(attachment));
|
|
8764
|
+
}
|
|
8765
|
+
imageAttachmentIds.push(id);
|
|
8712
8766
|
} else {
|
|
8713
8767
|
parts.push(imagePartForAttachment(attachment));
|
|
8714
8768
|
imageAttachmentIds.push(id);
|
|
@@ -8747,6 +8801,15 @@ function imagePartForAttachment(att) {
|
|
|
8747
8801
|
imageUrl: { url: `data:${att.mime};base64,${base64}` }
|
|
8748
8802
|
};
|
|
8749
8803
|
}
|
|
8804
|
+
/** Persist bytes to a temp file when path delivery needs a disk path. */
|
|
8805
|
+
function ensureImagePath(att) {
|
|
8806
|
+
if (att.sourcePath !== void 0 && att.sourcePath.length > 0) return att.sourcePath;
|
|
8807
|
+
const ext = att.mime === "image/jpeg" ? "jpg" : att.mime.split("/")[1]?.replace("+xml", "").replace("+json", "") ?? "png";
|
|
8808
|
+
const path = join(tmpdir(), `${TEMP_ATTACHMENT_PREFIX}${randomUUID()}.${ext}`);
|
|
8809
|
+
writeFileSync(path, att.bytes);
|
|
8810
|
+
att.sourcePath = path;
|
|
8811
|
+
return path;
|
|
8812
|
+
}
|
|
8750
8813
|
function tagTextForVideo(att) {
|
|
8751
8814
|
return formatMediaTag("video", att.sourcePath);
|
|
8752
8815
|
}
|
|
@@ -8914,7 +8977,8 @@ var InputController = class InputController {
|
|
|
8914
8977
|
this.dispatchUserInput(text, session);
|
|
8915
8978
|
}
|
|
8916
8979
|
dispatchUserInput(text, session) {
|
|
8917
|
-
const
|
|
8980
|
+
const canInlineImages = this.supportsCurrentModelCapability("image_in");
|
|
8981
|
+
const extraction = extractMediaAttachments(text, this.host.imageStore, { imageMode: canInlineImages ? "inline" : "path" });
|
|
8918
8982
|
if (!this.validateMediaCapabilities(extraction)) return;
|
|
8919
8983
|
if (extraction.hasMedia) this.sendMessage(session, text, {
|
|
8920
8984
|
hasMedia: true,
|
|
@@ -9091,10 +9155,6 @@ var InputController = class InputController {
|
|
|
9091
9155
|
}
|
|
9092
9156
|
validateMediaCapabilities(extraction) {
|
|
9093
9157
|
if (!extraction.hasMedia) return true;
|
|
9094
|
-
if (extraction.imageAttachmentIds.length > 0 && !this.supportsCurrentModelCapability("image_in")) {
|
|
9095
|
-
this.host.showError(t("error.image_not_supported"));
|
|
9096
|
-
return false;
|
|
9097
|
-
}
|
|
9098
9158
|
if (extraction.videoAttachmentIds.length > 0 && !this.supportsCurrentModelCapability("video_in")) {
|
|
9099
9159
|
this.host.showError(t("error.video_not_supported"));
|
|
9100
9160
|
return false;
|
|
@@ -9926,6 +9986,20 @@ function extractBracketedImagePastePaths(data) {
|
|
|
9926
9986
|
if (paths.length === 0 || segmentStart !== pasted.length) return void 0;
|
|
9927
9987
|
return paths;
|
|
9928
9988
|
}
|
|
9989
|
+
/**
|
|
9990
|
+
* True only when bracketed-paste markers span the entire input and the
|
|
9991
|
+
* body is strictly empty — Cmd+V with an image-only clipboard (macOS
|
|
9992
|
+
* wraps nothing). Whitespace-only pastes and coalesced keystrokes around
|
|
9993
|
+
* the marker pair are not image pastes.
|
|
9994
|
+
*/
|
|
9995
|
+
function isCompleteEmptyBracketedPaste(data) {
|
|
9996
|
+
if (!data.includes(BRACKET_PASTE_START)) return false;
|
|
9997
|
+
const startIndex = data.indexOf(BRACKET_PASTE_START);
|
|
9998
|
+
const endIndex = data.indexOf(BRACKET_PASTE_END, startIndex + 6);
|
|
9999
|
+
if (endIndex === -1) return false;
|
|
10000
|
+
if (startIndex !== 0 || endIndex + 6 !== data.length) return false;
|
|
10001
|
+
return data.slice(startIndex + 6, endIndex).length === 0;
|
|
10002
|
+
}
|
|
9929
10003
|
const KITTY_CSI_U = /^\[(\d+);(\d+)((?::\d+)*)u$/;
|
|
9930
10004
|
const CAPS_LOCK_BIT = 64;
|
|
9931
10005
|
const CTRL_BIT = 4;
|
|
@@ -10138,6 +10212,11 @@ var CustomEditor = class extends Editor {
|
|
|
10138
10212
|
if (!normalized.includes(BRACKET_PASTE_END)) this.consumingPaste = true;
|
|
10139
10213
|
return;
|
|
10140
10214
|
}
|
|
10215
|
+
if (this.onPasteImage !== void 0 && isCompleteEmptyBracketedPaste(normalized)) {
|
|
10216
|
+
const handler = this.onPasteImage;
|
|
10217
|
+
handler();
|
|
10218
|
+
return;
|
|
10219
|
+
}
|
|
10141
10220
|
if (matchesKey(normalized, process.platform === "win32" ? "alt+v" : Key.ctrl("v"))) {
|
|
10142
10221
|
if (this.expandPasteMarkerAtCursor()) return;
|
|
10143
10222
|
if (this.onPasteImage !== void 0) {
|
|
@@ -14053,7 +14132,7 @@ var ScreamTUI = class {
|
|
|
14053
14132
|
const card = new OnboardingCardComponent({
|
|
14054
14133
|
colors: this.state.theme.colors,
|
|
14055
14134
|
onConfigure: () => {
|
|
14056
|
-
import("./dispatch-
|
|
14135
|
+
import("./dispatch-Du8ddILK.mjs").then(({ handleConnectCommand }) => handleConnectCommand(this, "")).finally(() => {
|
|
14057
14136
|
this.restoreEditor();
|
|
14058
14137
|
onDone?.();
|
|
14059
14138
|
});
|