flavor-code 1.4.1 → 1.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/README.zh-CN.md +5 -2
- package/dist/{app-4YRKE7VI.js → app-4CUS3GEJ.js} +340 -165
- package/dist/{chunk-ZJCAQXA7.js → chunk-B23V72YR.js} +1 -0
- package/dist/{chunk-FAORPP4F.js → chunk-KMBDK4SN.js} +1 -1
- package/dist/{chunk-O2PC44GY.js → chunk-QKND3FX7.js} +8 -25
- package/dist/{chunk-VMQWXQEC.js → chunk-W2TIY6JY.js} +11 -1
- package/dist/{claude-ink-JZXNSAQS.js → claude-ink-VQU3C5UL.js} +2 -2
- package/dist/cli-main.js +5 -5
- package/dist/desktop/main.js +7 -24
- package/dist/desktop-renderer/assets/index-CPXrzFgv.js +154 -0
- package/dist/desktop-renderer/assets/{interactive-terminal-1agnYY5L.js → interactive-terminal-ouQQ3brz.js} +1 -1
- package/dist/desktop-renderer/index.html +1 -1
- package/dist/sdk/index.js +3 -3
- package/dist/ui/commands.d.ts +1 -5
- package/dist/utils/execFileNoThrow.d.ts +1 -0
- package/package.json +1 -1
- package/dist/desktop-renderer/assets/index-BM9ugkh9.js +0 -154
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
thinkingWindow,
|
|
20
20
|
transcriptReducer,
|
|
21
21
|
withTimeout
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-QKND3FX7.js";
|
|
23
23
|
import "./chunk-N5MXHJKD.js";
|
|
24
24
|
import "./chunk-7YFHRORG.js";
|
|
25
25
|
import {
|
|
@@ -39,17 +39,17 @@ import {
|
|
|
39
39
|
useStdout,
|
|
40
40
|
use_app_default,
|
|
41
41
|
use_input_default
|
|
42
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-W2TIY6JY.js";
|
|
43
43
|
import {
|
|
44
44
|
execFileNoThrow,
|
|
45
45
|
getGraphemeSegmenter
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-B23V72YR.js";
|
|
47
47
|
import "./chunk-S32JRDZK.js";
|
|
48
48
|
|
|
49
49
|
// src/ui/app.tsx
|
|
50
50
|
import { basename as basename3 } from "path";
|
|
51
51
|
import { homedir } from "os";
|
|
52
|
-
import { useEffect as useEffect3, useReducer, useRef as useRef4, useState as useState2 } from "react";
|
|
52
|
+
import React4, { useEffect as useEffect3, useMemo as useMemo3, useReducer, useRef as useRef4, useState as useState2 } from "react";
|
|
53
53
|
|
|
54
54
|
// src/claude-ink/hooks/use-animation-frame.ts
|
|
55
55
|
import { useContext as useContext2, useEffect, useState } from "react";
|
|
@@ -1364,6 +1364,18 @@ var CANDIDATE_KIND_PRIORITY = {
|
|
|
1364
1364
|
command: 1,
|
|
1365
1365
|
tool: 2
|
|
1366
1366
|
};
|
|
1367
|
+
var SLASH_DESCRIPTION_CHAR_LIMIT = 240;
|
|
1368
|
+
function normalizeSlashDescription(description) {
|
|
1369
|
+
const singleLine = description.replace(/\s+/gu, " ").trim();
|
|
1370
|
+
const points = [...singleLine];
|
|
1371
|
+
if (points.length <= SLASH_DESCRIPTION_CHAR_LIMIT) return singleLine;
|
|
1372
|
+
return `${points.slice(0, SLASH_DESCRIPTION_CHAR_LIMIT - 1).join("")}\u2026`;
|
|
1373
|
+
}
|
|
1374
|
+
function optionalDescription(description) {
|
|
1375
|
+
if (description === void 0) return void 0;
|
|
1376
|
+
const normalized = normalizeSlashDescription(description);
|
|
1377
|
+
return normalized.length === 0 ? void 0 : normalized;
|
|
1378
|
+
}
|
|
1367
1379
|
function slashCandidatePresentation(selected) {
|
|
1368
1380
|
return {
|
|
1369
1381
|
marker: selected ? "\u203A " : " ",
|
|
@@ -1374,16 +1386,22 @@ function slashCandidatePresentation(selected) {
|
|
|
1374
1386
|
function buildSlashCandidates(commands, plugins, skills, tools = []) {
|
|
1375
1387
|
const candidates = /* @__PURE__ */ new Map();
|
|
1376
1388
|
for (const command of commands) {
|
|
1377
|
-
candidates.set(command.name, {
|
|
1389
|
+
candidates.set(command.name, {
|
|
1390
|
+
name: command.name,
|
|
1391
|
+
kind: "command",
|
|
1392
|
+
description: normalizeSlashDescription(command.description)
|
|
1393
|
+
});
|
|
1378
1394
|
}
|
|
1379
1395
|
for (const plugin of plugins) {
|
|
1380
1396
|
if (!candidates.has(plugin.name)) {
|
|
1381
|
-
|
|
1397
|
+
const description = optionalDescription(plugin.description);
|
|
1398
|
+
candidates.set(plugin.name, description === void 0 ? { name: plugin.name, kind: "plugin" } : { name: plugin.name, kind: "plugin", description });
|
|
1382
1399
|
}
|
|
1383
1400
|
}
|
|
1384
1401
|
for (const tool of tools) {
|
|
1385
1402
|
if (!candidates.has(tool.name)) {
|
|
1386
|
-
|
|
1403
|
+
const description = optionalDescription(tool.description);
|
|
1404
|
+
candidates.set(tool.name, description === void 0 ? { name: tool.name, kind: "tool" } : { name: tool.name, kind: "tool", description });
|
|
1387
1405
|
}
|
|
1388
1406
|
}
|
|
1389
1407
|
for (const skill of skills) {
|
|
@@ -1391,7 +1409,7 @@ function buildSlashCandidates(commands, plugins, skills, tools = []) {
|
|
|
1391
1409
|
candidates.set(skill.name, {
|
|
1392
1410
|
name: skill.name,
|
|
1393
1411
|
kind: "skill",
|
|
1394
|
-
description: skill.description,
|
|
1412
|
+
description: normalizeSlashDescription(skill.description),
|
|
1395
1413
|
source: skill.source
|
|
1396
1414
|
});
|
|
1397
1415
|
}
|
|
@@ -1779,6 +1797,16 @@ function isCode(error, code) {
|
|
|
1779
1797
|
// src/ui/clipboard-image.ts
|
|
1780
1798
|
var CLIPBOARD_TIMEOUT_MS = 1e4;
|
|
1781
1799
|
var NO_IMAGE_EXIT_CODE = 3;
|
|
1800
|
+
var NO_TEXT_EXIT_CODE = 3;
|
|
1801
|
+
var CLIPBOARD_IMAGE_MAX_BUFFER = Math.ceil(DEFAULT_MAX_IMAGE_BYTES / 3) * 4 + 64 * 1024;
|
|
1802
|
+
var READ_WINDOWS_CLIPBOARD_TEXT = String.raw`
|
|
1803
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
1804
|
+
if (-not [Windows.Forms.Clipboard]::ContainsText()) { exit 3 }
|
|
1805
|
+
$text = [Windows.Forms.Clipboard]::GetText()
|
|
1806
|
+
if ([string]::IsNullOrEmpty($text)) { exit 3 }
|
|
1807
|
+
$bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
|
|
1808
|
+
[Console]::Out.Write([Convert]::ToBase64String($bytes))
|
|
1809
|
+
`.trim();
|
|
1782
1810
|
var READ_WINDOWS_CLIPBOARD_IMAGE = String.raw`
|
|
1783
1811
|
Add-Type -AssemblyName System.Windows.Forms
|
|
1784
1812
|
Add-Type -AssemblyName System.Drawing
|
|
@@ -1843,8 +1871,47 @@ try {
|
|
|
1843
1871
|
$.exit(3);
|
|
1844
1872
|
}
|
|
1845
1873
|
`.trim();
|
|
1846
|
-
function
|
|
1847
|
-
|
|
1874
|
+
function clipboardPasteIntent(input, key, isPasted, platform = process.platform) {
|
|
1875
|
+
if (isPasted) return input.length === 0 ? "immediate" : void 0;
|
|
1876
|
+
const pasteModifier = platform === "darwin" ? key.super === true : key.ctrl;
|
|
1877
|
+
return pasteModifier && input.toLowerCase() === "v" ? "deferred" : void 0;
|
|
1878
|
+
}
|
|
1879
|
+
async function readClipboardContent(options = {}) {
|
|
1880
|
+
const text = await readClipboardText(options);
|
|
1881
|
+
if (text !== void 0) return { kind: "text", text };
|
|
1882
|
+
const attachment = await readClipboardImage(options);
|
|
1883
|
+
return attachment === void 0 ? void 0 : { kind: "image", attachment };
|
|
1884
|
+
}
|
|
1885
|
+
async function readClipboardText(options = {}) {
|
|
1886
|
+
const platform = options.platform ?? process.platform;
|
|
1887
|
+
if (platform === "win32") return readWindowsClipboardText({ ...options, platform });
|
|
1888
|
+
if (platform === "darwin") return readMacClipboardText({ ...options, platform });
|
|
1889
|
+
throw new Error("Pasting native clipboard content is currently supported on Windows and macOS only");
|
|
1890
|
+
}
|
|
1891
|
+
async function readWindowsClipboardText(options = {}) {
|
|
1892
|
+
const platform = options.platform ?? process.platform;
|
|
1893
|
+
if (platform !== "win32") throw new Error("Reading clipboard text this way is supported on Windows only");
|
|
1894
|
+
const result = await (options.run ?? execFileNoThrow)(
|
|
1895
|
+
"powershell.exe",
|
|
1896
|
+
["-NoProfile", "-NonInteractive", "-STA", "-Command", READ_WINDOWS_CLIPBOARD_TEXT],
|
|
1897
|
+
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
|
|
1898
|
+
);
|
|
1899
|
+
if (result.code === NO_TEXT_EXIT_CODE) return void 0;
|
|
1900
|
+
if (result.code !== 0) throw clipboardReadError("text", result);
|
|
1901
|
+
const encoded = result.stdout.trim();
|
|
1902
|
+
if (encoded.length === 0) return void 0;
|
|
1903
|
+
return Buffer.from(encoded, "base64").toString("utf8") || void 0;
|
|
1904
|
+
}
|
|
1905
|
+
async function readMacClipboardText(options = {}) {
|
|
1906
|
+
const platform = options.platform ?? process.platform;
|
|
1907
|
+
if (platform !== "darwin") throw new Error("Reading clipboard text this way is supported on macOS only");
|
|
1908
|
+
const result = await (options.run ?? execFileNoThrow)(
|
|
1909
|
+
"pbpaste",
|
|
1910
|
+
["-Prefer", "txt"],
|
|
1911
|
+
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
|
|
1912
|
+
);
|
|
1913
|
+
if (result.code !== 0 || result.stdout.length === 0) return void 0;
|
|
1914
|
+
return result.stdout;
|
|
1848
1915
|
}
|
|
1849
1916
|
async function readClipboardImage(options = {}) {
|
|
1850
1917
|
const platform = options.platform ?? process.platform;
|
|
@@ -1860,7 +1927,7 @@ async function readWindowsClipboardImage(options = {}) {
|
|
|
1860
1927
|
const result = await (options.run ?? execFileNoThrow)(
|
|
1861
1928
|
"powershell.exe",
|
|
1862
1929
|
["-NoProfile", "-NonInteractive", "-STA", "-Command", READ_WINDOWS_CLIPBOARD_IMAGE],
|
|
1863
|
-
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
|
|
1930
|
+
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false, maxBuffer: CLIPBOARD_IMAGE_MAX_BUFFER }
|
|
1864
1931
|
);
|
|
1865
1932
|
return attachmentFromResult(result, options.now?.() ?? /* @__PURE__ */ new Date());
|
|
1866
1933
|
}
|
|
@@ -1872,15 +1939,14 @@ async function readMacClipboardImage(options = {}) {
|
|
|
1872
1939
|
const result = await (options.run ?? execFileNoThrow)(
|
|
1873
1940
|
"osascript",
|
|
1874
1941
|
["-l", "JavaScript", "-e", READ_MAC_CLIPBOARD_IMAGE],
|
|
1875
|
-
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false }
|
|
1942
|
+
{ timeout: CLIPBOARD_TIMEOUT_MS, useCwd: false, maxBuffer: CLIPBOARD_IMAGE_MAX_BUFFER }
|
|
1876
1943
|
);
|
|
1877
1944
|
return attachmentFromResult(result, options.now?.() ?? /* @__PURE__ */ new Date());
|
|
1878
1945
|
}
|
|
1879
1946
|
function attachmentFromResult(result, now) {
|
|
1880
1947
|
if (result.code === NO_IMAGE_EXIT_CODE) return void 0;
|
|
1881
1948
|
if (result.code !== 0) {
|
|
1882
|
-
|
|
1883
|
-
throw new Error(detail ? `Could not read the clipboard image: ${detail}` : "Could not read the clipboard image");
|
|
1949
|
+
throw clipboardReadError("image", result);
|
|
1884
1950
|
}
|
|
1885
1951
|
const dataBase64 = result.stdout.trim();
|
|
1886
1952
|
if (dataBase64.length === 0) return void 0;
|
|
@@ -1890,6 +1956,10 @@ function attachmentFromResult(result, now) {
|
|
|
1890
1956
|
dataBase64
|
|
1891
1957
|
};
|
|
1892
1958
|
}
|
|
1959
|
+
function clipboardReadError(kind, result) {
|
|
1960
|
+
const detail = result.stderr.trim() || result.error?.trim();
|
|
1961
|
+
return new Error(detail ? `Could not read the clipboard ${kind}: ${detail}` : `Could not read the clipboard ${kind}`);
|
|
1962
|
+
}
|
|
1893
1963
|
function timestamp(value) {
|
|
1894
1964
|
const year = value.getUTCFullYear();
|
|
1895
1965
|
const month = String(value.getUTCMonth() + 1).padStart(2, "0");
|
|
@@ -1946,6 +2016,7 @@ var PromptHistoryStore = class {
|
|
|
1946
2016
|
// src/ui/app.tsx
|
|
1947
2017
|
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1948
2018
|
var HISTORY_CAP = 200;
|
|
2019
|
+
var CLIPBOARD_SHORTCUT_FALLBACK_MS = 300;
|
|
1949
2020
|
var BUILTIN_SLASH_CANDIDATES = MVP_COMMANDS.map((name) => ({ name, description: COMMAND_DESCRIPTIONS[name] }));
|
|
1950
2021
|
var PROMPT_HORIZONTAL_PADDING = 1;
|
|
1951
2022
|
function clonePromptDraft(state) {
|
|
@@ -1997,16 +2068,24 @@ function isPlatformShortcut(character, key, letter, platform = process.platform)
|
|
|
1997
2068
|
if (character.toLowerCase() !== letter.toLowerCase()) return false;
|
|
1998
2069
|
return platform === "darwin" ? key.super || key.ctrl : key.ctrl;
|
|
1999
2070
|
}
|
|
2071
|
+
function isOutputToggleShortcut(character, key) {
|
|
2072
|
+
return key.ctrl && character.toLowerCase() === "o";
|
|
2073
|
+
}
|
|
2074
|
+
function outputToggleShortcut(_platform = process.platform) {
|
|
2075
|
+
return "Ctrl+O";
|
|
2076
|
+
}
|
|
2000
2077
|
function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
2001
2078
|
if (input.length === 0 && cursor === 0 && images.length > 0) {
|
|
2002
2079
|
return { handled: true, images: images.slice(0, -1) };
|
|
2003
2080
|
}
|
|
2004
2081
|
return { handled: false, images: [...images] };
|
|
2005
2082
|
}
|
|
2006
|
-
function prepareCliSubmission(input, images) {
|
|
2083
|
+
function prepareCliSubmission(input, images, slashCommands = MVP_COMMANDS) {
|
|
2007
2084
|
const entered = input.trim();
|
|
2008
2085
|
if (entered.length === 0 && images.length === 0) return { kind: "empty" };
|
|
2009
|
-
|
|
2086
|
+
const slashName = /^\/(\S+)/u.exec(entered)?.[1]?.toLowerCase();
|
|
2087
|
+
const isSlashCommand = slashName !== void 0 && slashCommands.some((command) => command.toLowerCase() === slashName);
|
|
2088
|
+
if (images.length > 0 && isSlashCommand) {
|
|
2010
2089
|
return { kind: "error", message: "Image attachments cannot be used with slash commands." };
|
|
2011
2090
|
}
|
|
2012
2091
|
const text = entered || "Analyze the attached image(s).";
|
|
@@ -2123,11 +2202,13 @@ async function runTerminalSubmissionChain(options) {
|
|
|
2123
2202
|
if (prompt !== void 0) options.onPendingConsumed(options.pending.values);
|
|
2124
2203
|
}
|
|
2125
2204
|
}
|
|
2126
|
-
function classifyTerminalInput(key) {
|
|
2205
|
+
function classifyTerminalInput(key, activeSession = false) {
|
|
2127
2206
|
if (key.wheelUp) return { type: "scroll", rows: -3 };
|
|
2128
2207
|
if (key.wheelDown) return { type: "scroll", rows: 3 };
|
|
2129
2208
|
if (key.pageUp) return { type: "page", fraction: -0.5 };
|
|
2130
2209
|
if (key.pageDown) return { type: "page", fraction: 0.5 };
|
|
2210
|
+
if (activeSession && key.upArrow) return { type: "scroll", rows: -3 };
|
|
2211
|
+
if (activeSession && key.downArrow) return { type: "scroll", rows: 3 };
|
|
2131
2212
|
if (key.upArrow) return { type: "history", direction: "up" };
|
|
2132
2213
|
if (key.downArrow) return { type: "history", direction: "down" };
|
|
2133
2214
|
return null;
|
|
@@ -2200,6 +2281,8 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2200
2281
|
pendingPromptRef.current ??= new PendingPromptQueue();
|
|
2201
2282
|
const closing = useRef4(false);
|
|
2202
2283
|
const clipboardBusy = useRef4(false);
|
|
2284
|
+
const clipboardFallbackTimer = useRef4(null);
|
|
2285
|
+
const terminalTextPasteRevision = useRef4(0);
|
|
2203
2286
|
const textBuf = useRef4({ pending: "", timer: null });
|
|
2204
2287
|
const thinkingBuf = useRef4({ pending: "", timer: null });
|
|
2205
2288
|
const promptDraftRef = useRef4({
|
|
@@ -2216,6 +2299,9 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2216
2299
|
const promptHistoryStoreRef = useRef4(void 0);
|
|
2217
2300
|
promptHistoryStoreRef.current ??= new PromptHistoryStore({ home: home ?? homedir(), workspace, maxEntries: HISTORY_CAP });
|
|
2218
2301
|
promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
|
|
2302
|
+
useEffect3(() => () => {
|
|
2303
|
+
if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
|
|
2304
|
+
}, []);
|
|
2219
2305
|
const commitPromptDraft = (next, recordHistory = true) => {
|
|
2220
2306
|
const current = promptDraftRef.current;
|
|
2221
2307
|
const resolved = {
|
|
@@ -2459,7 +2545,10 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2459
2545
|
setCustomQuestionActive(false);
|
|
2460
2546
|
}, [questions]);
|
|
2461
2547
|
useEffect3(() => setApprovalExpanded(false), [approval?.id]);
|
|
2462
|
-
const derivedSlashCompletion =
|
|
2548
|
+
const derivedSlashCompletion = useMemo3(
|
|
2549
|
+
() => deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection),
|
|
2550
|
+
[input, promptCursor, slashCandidates, slashSelection]
|
|
2551
|
+
);
|
|
2463
2552
|
const slashCompletion = canShowSlashCompletion(
|
|
2464
2553
|
transcript.active !== void 0,
|
|
2465
2554
|
input,
|
|
@@ -2477,27 +2566,43 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2477
2566
|
setMentionSelection(0);
|
|
2478
2567
|
setDismissedMentionInput(next.text);
|
|
2479
2568
|
};
|
|
2480
|
-
const
|
|
2481
|
-
const active = runtimeRef.current;
|
|
2482
|
-
if (active === void 0) {
|
|
2483
|
-
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2484
|
-
return;
|
|
2485
|
-
}
|
|
2486
|
-
if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2487
|
-
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2488
|
-
return;
|
|
2489
|
-
}
|
|
2569
|
+
const pasteClipboardContent = async (imageOnly = false) => {
|
|
2490
2570
|
if (clipboardBusy.current) return;
|
|
2491
2571
|
clipboardBusy.current = true;
|
|
2492
|
-
|
|
2572
|
+
const pasteRevision = terminalTextPasteRevision.current;
|
|
2573
|
+
setClipboardNotice(imageOnly ? "Reading clipboard image..." : "Reading clipboard...");
|
|
2493
2574
|
try {
|
|
2494
|
-
const
|
|
2495
|
-
if (
|
|
2496
|
-
setClipboardNotice(
|
|
2575
|
+
const content = imageOnly ? await readClipboardImage().then((attachment2) => attachment2 === void 0 ? void 0 : { kind: "image", attachment: attachment2 }) : await readClipboardContent();
|
|
2576
|
+
if (pasteRevision !== terminalTextPasteRevision.current) {
|
|
2577
|
+
setClipboardNotice(void 0);
|
|
2578
|
+
return;
|
|
2579
|
+
}
|
|
2580
|
+
if (content === void 0) {
|
|
2581
|
+
setClipboardNotice(imageOnly ? "Clipboard does not contain an image." : "Clipboard does not contain pasteable text or an image.");
|
|
2582
|
+
return;
|
|
2583
|
+
}
|
|
2584
|
+
if (content.kind === "text") {
|
|
2585
|
+
const currentDraft2 = promptDraftRef.current;
|
|
2586
|
+
const nextPastedBlocks = /[\r\n]/u.test(content.text) ? [...currentDraft2.pastedBlocks, { id: currentDraft2.pastedBlocks.length + 1, text: content.text }] : currentDraft2.pastedBlocks;
|
|
2587
|
+
commitPromptDraft({
|
|
2588
|
+
...editPrompt({ text: currentDraft2.text, cursor: currentDraft2.cursor }, { type: "insert", value: content.text }),
|
|
2589
|
+
pastedBlocks: nextPastedBlocks
|
|
2590
|
+
});
|
|
2591
|
+
setClipboardNotice(void 0);
|
|
2592
|
+
return;
|
|
2593
|
+
}
|
|
2594
|
+
const active = runtimeRef.current;
|
|
2595
|
+
if (active === void 0) {
|
|
2596
|
+
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2497
2597
|
return;
|
|
2498
2598
|
}
|
|
2499
|
-
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2500
2599
|
const currentDraft = promptDraftRef.current;
|
|
2600
|
+
if (currentDraft.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2601
|
+
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2602
|
+
return;
|
|
2603
|
+
}
|
|
2604
|
+
const attachment = content.attachment;
|
|
2605
|
+
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2501
2606
|
const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
|
|
2502
2607
|
if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
|
|
2503
2608
|
throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
|
|
@@ -2513,7 +2618,10 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2513
2618
|
}
|
|
2514
2619
|
};
|
|
2515
2620
|
use_input_default((character, key, event) => {
|
|
2516
|
-
const terminalAction = classifyTerminalInput(
|
|
2621
|
+
const terminalAction = classifyTerminalInput(
|
|
2622
|
+
key,
|
|
2623
|
+
transcript.active !== void 0 && slashCompletion === null && mentionCompletion === null
|
|
2624
|
+
);
|
|
2517
2625
|
if (terminalAction?.type === "scroll") {
|
|
2518
2626
|
const scroll = selectWheelScrollTarget(
|
|
2519
2627
|
scrollRef.current,
|
|
@@ -2534,7 +2642,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2534
2642
|
}
|
|
2535
2643
|
const active = runtimeRef.current;
|
|
2536
2644
|
if (isCopyShortcut(character, key)) {
|
|
2537
|
-
if (selection.hasSelection()) selection.
|
|
2645
|
+
if (selection.hasSelection()) selection.copySelectionNoClear();
|
|
2538
2646
|
else if (process.platform !== "darwin") interrupt();
|
|
2539
2647
|
return;
|
|
2540
2648
|
}
|
|
@@ -2542,13 +2650,30 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2542
2650
|
interrupt();
|
|
2543
2651
|
return;
|
|
2544
2652
|
}
|
|
2545
|
-
if (
|
|
2653
|
+
if (isOutputToggleShortcut(character, key)) {
|
|
2546
2654
|
setExpandedOutput((value) => !value);
|
|
2547
|
-
scrollRef.current?.scrollToBottom();
|
|
2548
2655
|
return;
|
|
2549
2656
|
}
|
|
2550
|
-
if (
|
|
2551
|
-
|
|
2657
|
+
if (event.keypress.isPasted && character.length > 0) {
|
|
2658
|
+
terminalTextPasteRevision.current += 1;
|
|
2659
|
+
if (clipboardFallbackTimer.current !== null) {
|
|
2660
|
+
clearTimeout(clipboardFallbackTimer.current);
|
|
2661
|
+
clipboardFallbackTimer.current = null;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
const pasteIntent = clipboardPasteIntent(character, key, event.keypress.isPasted);
|
|
2665
|
+
if (pasteIntent === "immediate") {
|
|
2666
|
+
if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
|
|
2667
|
+
clipboardFallbackTimer.current = null;
|
|
2668
|
+
void pasteClipboardContent();
|
|
2669
|
+
return;
|
|
2670
|
+
}
|
|
2671
|
+
if (pasteIntent === "deferred") {
|
|
2672
|
+
if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
|
|
2673
|
+
clipboardFallbackTimer.current = setTimeout(() => {
|
|
2674
|
+
clipboardFallbackTimer.current = null;
|
|
2675
|
+
void pasteClipboardContent();
|
|
2676
|
+
}, CLIPBOARD_SHORTCUT_FALLBACK_MS);
|
|
2552
2677
|
return;
|
|
2553
2678
|
}
|
|
2554
2679
|
if (active?.approvals.pending !== void 0) {
|
|
@@ -2706,8 +2831,19 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2706
2831
|
return;
|
|
2707
2832
|
}
|
|
2708
2833
|
if (key.return) {
|
|
2834
|
+
if (/^\/paste-image\s*$/iu.test(input)) {
|
|
2835
|
+
setInput("");
|
|
2836
|
+
setPromptCursor(0);
|
|
2837
|
+
setPastedBlocks([]);
|
|
2838
|
+
promptDraftRef.current = { text: "", cursor: 0, pastedBlocks: [], imageAttachments };
|
|
2839
|
+
promptEditHistory.current.reset();
|
|
2840
|
+
setSlashSelection(0);
|
|
2841
|
+
setDismissedSlashInput(void 0);
|
|
2842
|
+
void pasteClipboardContent(true);
|
|
2843
|
+
return;
|
|
2844
|
+
}
|
|
2709
2845
|
const images = [...imageAttachments];
|
|
2710
|
-
const prepared = prepareCliSubmission(input, images);
|
|
2846
|
+
const prepared = prepareCliSubmission(input, images, slashCandidates.map(({ name }) => name));
|
|
2711
2847
|
if (prepared.kind === "empty" || active === void 0) return;
|
|
2712
2848
|
if (prepared.kind === "error") {
|
|
2713
2849
|
setClipboardNotice(prepared.message);
|
|
@@ -2914,6 +3050,25 @@ var CLI_VISIBLE_TURN_LIMIT = 40;
|
|
|
2914
3050
|
var CLI_VISIBLE_BLOCK_LIMIT = 320;
|
|
2915
3051
|
var CLI_VISIBLE_BLOCKS_PER_TURN = 80;
|
|
2916
3052
|
var CLI_VISIBLE_TEXT_CHARS = 32e3;
|
|
3053
|
+
function cliRenderBudget(rows, columns) {
|
|
3054
|
+
const viewportRows = Math.max(8, Math.floor(rows));
|
|
3055
|
+
const viewportColumns = Math.max(20, Math.floor(columns));
|
|
3056
|
+
const screenMultiplier = 4;
|
|
3057
|
+
const blockMultiplier = 2;
|
|
3058
|
+
const blocks = Math.min(
|
|
3059
|
+
CLI_VISIBLE_BLOCK_LIMIT,
|
|
3060
|
+
Math.max(24, viewportRows * blockMultiplier)
|
|
3061
|
+
);
|
|
3062
|
+
return {
|
|
3063
|
+
turns: Math.min(16, Math.max(4, Math.ceil(viewportRows / 4))),
|
|
3064
|
+
blocks,
|
|
3065
|
+
blocksPerTurn: Math.min(CLI_VISIBLE_BLOCKS_PER_TURN, blocks),
|
|
3066
|
+
textChars: Math.min(
|
|
3067
|
+
12e3,
|
|
3068
|
+
Math.max(4e3, viewportRows * viewportColumns * screenMultiplier)
|
|
3069
|
+
)
|
|
3070
|
+
};
|
|
3071
|
+
}
|
|
2917
3072
|
function approvalDetailLines(approval) {
|
|
2918
3073
|
const lines = [];
|
|
2919
3074
|
if (approval.agent !== "main") lines.push(`Agent: ${approval.agent}`);
|
|
@@ -2963,25 +3118,32 @@ function boundedCliDisplayText(text, limit = CLI_VISIBLE_TEXT_CHARS) {
|
|
|
2963
3118
|
|
|
2964
3119
|
${text.slice(-half)}`;
|
|
2965
3120
|
}
|
|
2966
|
-
function boundedCliPresentation(presentation) {
|
|
3121
|
+
function boundedCliPresentation(presentation, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
|
|
2967
3122
|
if (presentation.kind === "terminal") return {
|
|
2968
3123
|
...presentation,
|
|
2969
|
-
...presentation.stdout === void 0 ? {} : { stdout: boundedCliDisplayText(presentation.stdout) },
|
|
2970
|
-
...presentation.stderr === void 0 ? {} : { stderr: boundedCliDisplayText(presentation.stderr) }
|
|
3124
|
+
...presentation.stdout === void 0 ? {} : { stdout: boundedCliDisplayText(presentation.stdout, maxTextChars) },
|
|
3125
|
+
...presentation.stderr === void 0 ? {} : { stderr: boundedCliDisplayText(presentation.stderr, maxTextChars) }
|
|
2971
3126
|
};
|
|
2972
3127
|
if (presentation.kind === "job" && presentation.output !== void 0) return {
|
|
2973
3128
|
...presentation,
|
|
2974
|
-
output: boundedCliDisplayText(presentation.output)
|
|
3129
|
+
output: boundedCliDisplayText(presentation.output, maxTextChars)
|
|
2975
3130
|
};
|
|
2976
3131
|
return presentation;
|
|
2977
3132
|
}
|
|
2978
|
-
function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN) {
|
|
3133
|
+
function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
|
|
2979
3134
|
const blockLimit = Math.max(1, Math.floor(maxBlocks));
|
|
2980
3135
|
const hiddenBlocks = Math.max(0, turn.blocks.length - blockLimit);
|
|
2981
|
-
const visible = turn.blocks.slice(-blockLimit).map((block) => block.kind === "text" ? { ...block, text: boundedCliDisplayText(block.text) } : {
|
|
3136
|
+
const visible = turn.blocks.slice(-blockLimit).map((block) => block.kind === "text" ? { ...block, text: boundedCliDisplayText(block.text, maxTextChars) } : {
|
|
2982
3137
|
...block,
|
|
2983
|
-
...block.details === void 0 ? {} : {
|
|
2984
|
-
|
|
3138
|
+
...block.details === void 0 ? {} : {
|
|
3139
|
+
details: boundedCliDisplayText(
|
|
3140
|
+
block.details,
|
|
3141
|
+
block.tool !== void 0 || block.presentation !== void 0 ? CLI_VISIBLE_TEXT_CHARS : maxTextChars
|
|
3142
|
+
)
|
|
3143
|
+
},
|
|
3144
|
+
...block.presentation === void 0 ? {} : {
|
|
3145
|
+
presentation: boundedCliPresentation(block.presentation, CLI_VISIBLE_TEXT_CHARS)
|
|
3146
|
+
}
|
|
2985
3147
|
});
|
|
2986
3148
|
const blocks = hiddenBlocks === 0 ? visible : [{
|
|
2987
3149
|
kind: "status",
|
|
@@ -2999,7 +3161,7 @@ function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN) {
|
|
|
2999
3161
|
}
|
|
3000
3162
|
};
|
|
3001
3163
|
}
|
|
3002
|
-
function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBlocks = CLI_VISIBLE_BLOCK_LIMIT) {
|
|
3164
|
+
function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBlocks = CLI_VISIBLE_BLOCK_LIMIT, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
|
|
3003
3165
|
const turns = [];
|
|
3004
3166
|
let remainingBlocks = Math.max(1, Math.floor(maxBlocks));
|
|
3005
3167
|
let hiddenBlocks = 0;
|
|
@@ -3007,7 +3169,7 @@ function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBl
|
|
|
3007
3169
|
const source = completed[index];
|
|
3008
3170
|
if (remainingBlocks <= 0) break;
|
|
3009
3171
|
const allowance = Math.min(CLI_VISIBLE_BLOCKS_PER_TURN, remainingBlocks);
|
|
3010
|
-
const bounded = boundedCliTurn(source, allowance);
|
|
3172
|
+
const bounded = boundedCliTurn(source, allowance, maxTextChars);
|
|
3011
3173
|
turns.push(bounded.turn);
|
|
3012
3174
|
hiddenBlocks += bounded.hiddenBlocks;
|
|
3013
3175
|
remainingBlocks -= Math.min(source.blocks.length, allowance);
|
|
@@ -3054,24 +3216,31 @@ function TerminalLayout({
|
|
|
3054
3216
|
ideContext
|
|
3055
3217
|
}) {
|
|
3056
3218
|
const dividerWidth = Math.max(1, columns - 1);
|
|
3219
|
+
const outputShortcut = outputToggleShortcut();
|
|
3057
3220
|
const showWelcome = completed.length === 0 && active === void 0;
|
|
3058
|
-
const
|
|
3059
|
-
|
|
3060
|
-
|
|
3221
|
+
const budget = useMemo3(
|
|
3222
|
+
() => cliRenderBudget(rows, columns),
|
|
3223
|
+
[rows, columns]
|
|
3224
|
+
);
|
|
3225
|
+
const activeTaskBlocks = useMemo3(() => active?.blocks.filter(
|
|
3061
3226
|
(block) => block.kind === "status" && block.task !== void 0
|
|
3062
|
-
) ?? [];
|
|
3063
|
-
const
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3227
|
+
) ?? [], [active]);
|
|
3228
|
+
const activeWithoutTasks = useMemo3(() => {
|
|
3229
|
+
if (active === void 0) return void 0;
|
|
3230
|
+
const raw = {
|
|
3231
|
+
...active,
|
|
3232
|
+
blocks: active.blocks.filter((block) => !(block.kind === "status" && block.task !== void 0))
|
|
3233
|
+
};
|
|
3234
|
+
return boundedCliTurn(raw, budget.blocksPerTurn, budget.textChars).turn;
|
|
3235
|
+
}, [active, budget]);
|
|
3236
|
+
const completedWindow = useMemo3(
|
|
3237
|
+
() => cliTranscriptWindow(completed, budget.turns, budget.blocks, budget.textChars),
|
|
3238
|
+
[completed, budget]
|
|
3239
|
+
);
|
|
3071
3240
|
const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
|
|
3072
3241
|
const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
|
|
3073
3242
|
const approvalRows = approval === void 0 ? 0 : 3 + (approvalExpanded ? approvalDetailLines(approval).length : 0);
|
|
3074
|
-
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows +
|
|
3243
|
+
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
|
|
3075
3244
|
const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
|
|
3076
3245
|
const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
|
|
3077
3246
|
const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
|
|
@@ -3090,7 +3259,7 @@ function TerminalLayout({
|
|
|
3090
3259
|
completedWindow.hiddenTurns,
|
|
3091
3260
|
" earlier turns and ",
|
|
3092
3261
|
completedWindow.hiddenBlocks,
|
|
3093
|
-
" output items hidden
|
|
3262
|
+
" output items hidden to keep the terminal responsive"
|
|
3094
3263
|
] }) : null,
|
|
3095
3264
|
completedWindow.turns.map((turn, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3096
3265
|
index > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
@@ -3113,82 +3282,86 @@ function TerminalLayout({
|
|
|
3113
3282
|
...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
|
|
3114
3283
|
}
|
|
3115
3284
|
),
|
|
3116
|
-
/* @__PURE__ */ jsxs4(Box_default, {
|
|
3117
|
-
|
|
3118
|
-
/* @__PURE__ */
|
|
3119
|
-
|
|
3120
|
-
|
|
3285
|
+
/* @__PURE__ */ jsxs4(Box_default, { position: "relative", flexShrink: 0, width: "100%", children: [
|
|
3286
|
+
completion === void 0 && mentionCompletion === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { position: "absolute", bottom: "100%", left: 0, right: 0, flexDirection: "column", opaque: true, children: [
|
|
3287
|
+
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
3288
|
+
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } })
|
|
3289
|
+
] }),
|
|
3290
|
+
/* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", flexShrink: 0, maxHeight: bottomMaxRows, width: "100%", overflowY: "hidden", children: [
|
|
3291
|
+
approval === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", marginBottom: 1, children: [
|
|
3292
|
+
/* @__PURE__ */ jsxs4(Text, { color: "magenta", children: [
|
|
3293
|
+
"\u250C\u2500 approval \xB7 ",
|
|
3294
|
+
approval.tool
|
|
3295
|
+
] }),
|
|
3296
|
+
/* @__PURE__ */ jsxs4(Text, { wrap: "truncate-end", color: "magentaBright", children: [
|
|
3297
|
+
"\u2502 ",
|
|
3298
|
+
approval.reason ?? "This action needs permission."
|
|
3299
|
+
] }),
|
|
3300
|
+
approvalExpanded ? approvalDetailLines(approval).map((line, index) => /* @__PURE__ */ jsxs4(Text, { color: "magentaBright", wrap: "truncate-end", children: [
|
|
3301
|
+
"\u2502 ",
|
|
3302
|
+
line
|
|
3303
|
+
] }, `${approval.id}:detail:${index}`)) : null,
|
|
3304
|
+
isDestructiveTool(approval.tool) || approval.allowAlways === false ? /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
3305
|
+
"\u2514\u2500 ",
|
|
3306
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3307
|
+
"=details / ",
|
|
3308
|
+
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
3309
|
+
"=once / ",
|
|
3310
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3311
|
+
"=accept edits / ",
|
|
3312
|
+
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
3313
|
+
"=deny"
|
|
3314
|
+
] }) : /* @__PURE__ */ jsxs4(Text, { bold: true, color: "magenta", children: [
|
|
3315
|
+
"\u2514\u2500 ",
|
|
3316
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "v" }),
|
|
3317
|
+
"=details / ",
|
|
3318
|
+
/* @__PURE__ */ jsx5(Text, { color: "green", children: "y" }),
|
|
3319
|
+
"=once / ",
|
|
3320
|
+
/* @__PURE__ */ jsx5(Text, { color: "yellow", children: "a" }),
|
|
3321
|
+
"=same-type / ",
|
|
3322
|
+
/* @__PURE__ */ jsx5(Text, { color: "cyan", children: "e" }),
|
|
3323
|
+
"=accept edits / ",
|
|
3324
|
+
/* @__PURE__ */ jsx5(Text, { color: "red", children: "n" }),
|
|
3325
|
+
"=deny"
|
|
3326
|
+
] })
|
|
3121
3327
|
] }),
|
|
3122
|
-
/* @__PURE__ */
|
|
3123
|
-
|
|
3124
|
-
|
|
3328
|
+
!questions || questions.length === 0 ? null : /* @__PURE__ */ jsx5(QuestionCards, { questions, activeIndex: questionIndex, answers: questionAnswers, customActive: customQuestionActive }),
|
|
3329
|
+
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
3330
|
+
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
3331
|
+
"Pending (",
|
|
3332
|
+
pendingPrompts.length,
|
|
3333
|
+
") \xB7 ",
|
|
3334
|
+
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
3335
|
+
" \xB7 Esc edit latest"
|
|
3125
3336
|
] }),
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
] })
|
|
3154
|
-
!questions || questions.length === 0 ? null : /* @__PURE__ */ jsx5(QuestionCards, { questions, activeIndex: questionIndex, answers: questionAnswers, customActive: customQuestionActive }),
|
|
3155
|
-
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
3156
|
-
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
3157
|
-
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
|
|
3158
|
-
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
3159
|
-
"Pending (",
|
|
3160
|
-
pendingPrompts.length,
|
|
3161
|
-
") \xB7 ",
|
|
3162
|
-
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
3163
|
-
" \xB7 Esc edit latest"
|
|
3164
|
-
] }),
|
|
3165
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
3166
|
-
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
3167
|
-
"[Image #",
|
|
3168
|
-
index + 1,
|
|
3169
|
-
"] ",
|
|
3170
|
-
image.name ?? basename3(image.source.path)
|
|
3171
|
-
] }, `${image.sha256}:${index}`)),
|
|
3172
|
-
clipboardNotice === void 0 ? null : /* @__PURE__ */ jsx5(Text, { color: "yellow", wrap: "truncate-end", children: clipboardNotice }),
|
|
3173
|
-
/* @__PURE__ */ jsx5(
|
|
3174
|
-
PromptLine,
|
|
3175
|
-
{
|
|
3176
|
-
input,
|
|
3177
|
-
pastedBlocks,
|
|
3178
|
-
cursor: promptCursor,
|
|
3179
|
-
columns,
|
|
3180
|
-
maxVisibleLines: promptMaxLines,
|
|
3181
|
-
completedSlashTokenLength: tokenLength,
|
|
3182
|
-
...onPromptCursorChange === void 0 ? {} : { onCursorChange: onPromptCursorChange }
|
|
3183
|
-
}
|
|
3184
|
-
),
|
|
3185
|
-
/* @__PURE__ */ jsx5(
|
|
3186
|
-
FooterStatus,
|
|
3187
|
-
{
|
|
3188
|
-
hint: activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 Ctrl/Cmd+O ${expandedOutput ? "collapse" : "expand"} output` : completion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 Esc close" : mentionCompletion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 click choose \xB7 Esc close" : `Enter send \xB7 \u2191\u2193/Ctrl/Cmd+R history \xB7 Ctrl/Cmd+O ${expandedOutput ? "collapse" : "expand"} output \xB7 Ctrl+C exit`,
|
|
3189
|
-
...ideContext === void 0 ? {} : { ideContext }
|
|
3190
|
-
}
|
|
3191
|
-
)
|
|
3337
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
3338
|
+
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
3339
|
+
"[Image #",
|
|
3340
|
+
index + 1,
|
|
3341
|
+
"] ",
|
|
3342
|
+
image.name ?? basename3(image.source.path)
|
|
3343
|
+
] }, `${image.sha256}:${index}`)),
|
|
3344
|
+
clipboardNotice === void 0 ? null : /* @__PURE__ */ jsx5(Text, { color: "yellow", wrap: "truncate-end", children: clipboardNotice }),
|
|
3345
|
+
/* @__PURE__ */ jsx5(
|
|
3346
|
+
PromptLine,
|
|
3347
|
+
{
|
|
3348
|
+
input,
|
|
3349
|
+
pastedBlocks,
|
|
3350
|
+
cursor: promptCursor,
|
|
3351
|
+
columns,
|
|
3352
|
+
maxVisibleLines: promptMaxLines,
|
|
3353
|
+
completedSlashTokenLength: tokenLength,
|
|
3354
|
+
...onPromptCursorChange === void 0 ? {} : { onCursorChange: onPromptCursorChange }
|
|
3355
|
+
}
|
|
3356
|
+
),
|
|
3357
|
+
/* @__PURE__ */ jsx5(
|
|
3358
|
+
FooterStatus,
|
|
3359
|
+
{
|
|
3360
|
+
hint: completion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 Esc close" : mentionCompletion !== void 0 ? "\u2191/\u2193 select \xB7 Tab complete \xB7 click choose \xB7 Esc close" : activeSession ? `Esc ${pendingPrompts.length > 0 ? "edit latest" : "stop"} \xB7 Ctrl+C cancel \xB7 Enter queue \xB7 Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse" : "expand"} tools` : `Enter send \xB7 \u2191\u2193/Ctrl/Cmd+R history \xB7 ${outputShortcut} ${expandedOutput ? "collapse" : "expand"} tools \xB7 Ctrl+C exit`,
|
|
3361
|
+
...ideContext === void 0 ? {} : { ideContext }
|
|
3362
|
+
}
|
|
3363
|
+
)
|
|
3364
|
+
] })
|
|
3192
3365
|
] })
|
|
3193
3366
|
] });
|
|
3194
3367
|
}
|
|
@@ -3290,7 +3463,7 @@ function SlashMenu({ completion }) {
|
|
|
3290
3463
|
presentation.marker,
|
|
3291
3464
|
/* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
|
|
3292
3465
|
candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
|
|
3293
|
-
candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${candidate.description}` })
|
|
3466
|
+
candidate.description === void 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` ${normalizeSlashDescription(candidate.description)}` })
|
|
3294
3467
|
] }, `${candidate.kind}:${candidate.name}`);
|
|
3295
3468
|
}) });
|
|
3296
3469
|
}
|
|
@@ -3369,7 +3542,7 @@ function scrollUp(scroll, amount) {
|
|
|
3369
3542
|
function TurnSeparator({ width }) {
|
|
3370
3543
|
return /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(Math.max(1, width - 1)) });
|
|
3371
3544
|
}
|
|
3372
|
-
|
|
3545
|
+
var TurnView = React4.memo(function TurnView2({
|
|
3373
3546
|
turn,
|
|
3374
3547
|
interactive,
|
|
3375
3548
|
workspaceName,
|
|
@@ -3408,11 +3581,11 @@ function TurnView({
|
|
|
3408
3581
|
] }),
|
|
3409
3582
|
/* @__PURE__ */ jsx5(Box_default, { flexDirection: "column", paddingLeft: 2, marginTop: 1, children: turn.blocks.map((block, index) => block.kind === "status" ? /* @__PURE__ */ jsx5(StatusBlockView, { block, interactive, workspaceName, expandedOutput }, block.id) : /* @__PURE__ */ jsx5(Box_default, { marginBottom: 1, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.text }) }, `${turn.id}-text-${index}`)) })
|
|
3410
3583
|
] });
|
|
3411
|
-
}
|
|
3584
|
+
});
|
|
3412
3585
|
var DIFF_CONTENT = fileDiffLineStyle("context").contentColor;
|
|
3413
3586
|
var DIFF_REMOVED_MARKER = fileDiffLineStyle("removed").markerColor;
|
|
3414
3587
|
var DIFF_ADDED_MARKER = fileDiffLineStyle("added").markerColor;
|
|
3415
|
-
function FileDiffView({ presentation }) {
|
|
3588
|
+
function FileDiffView({ presentation, expanded }) {
|
|
3416
3589
|
const operation = presentation.operation === "create" ? "Create" : presentation.operation === "delete" ? "Delete" : "Update";
|
|
3417
3590
|
if (presentation.operation === "delete") {
|
|
3418
3591
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", children: [
|
|
@@ -3444,7 +3617,7 @@ function FileDiffView({ presentation }) {
|
|
|
3444
3617
|
", removed ",
|
|
3445
3618
|
lineCount(presentation.removed)
|
|
3446
3619
|
] }),
|
|
3447
|
-
presentation.lines.map((line, index) => /* @__PURE__ */ jsx5(FileDiffRow, { line, lineWidth }, `${line.kind}:${line.oldLine ?? ""}:${line.newLine ?? ""}:${index}`))
|
|
3620
|
+
(expanded ? presentation.lines : []).map((line, index) => /* @__PURE__ */ jsx5(FileDiffRow, { line, lineWidth }, `${line.kind}:${line.oldLine ?? ""}:${line.newLine ?? ""}:${index}`))
|
|
3448
3621
|
] });
|
|
3449
3622
|
}
|
|
3450
3623
|
function FileDiffRow({ line, lineWidth }) {
|
|
@@ -3590,6 +3763,7 @@ function StatusBlockView({
|
|
|
3590
3763
|
}) {
|
|
3591
3764
|
const visibleBlock = cliToolTitle(block);
|
|
3592
3765
|
const outcome = cliToolOutcome(block);
|
|
3766
|
+
const toolOutput = block.tool !== void 0 || block.presentation !== void 0;
|
|
3593
3767
|
const primary = visibleBlock.activity === "model" || visibleBlock.task !== void 0 ? /* @__PURE__ */ jsx5(TaskStatusLine, { block: visibleBlock, interactive }) : visibleBlock.state === "completed" && visibleBlock.presentation !== void 0 ? /* @__PURE__ */ jsx5(ToolPresentationView, { presentation: visibleBlock.presentation, workspaceName, expandedOutput }) : /* @__PURE__ */ jsx5(StatusLine, { block: visibleBlock, interactive });
|
|
3594
3768
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3595
3769
|
primary,
|
|
@@ -3597,7 +3771,7 @@ function StatusBlockView({
|
|
|
3597
3771
|
"\u2514 ",
|
|
3598
3772
|
outcome
|
|
3599
3773
|
] }) }),
|
|
3600
|
-
block.details === void 0 || block.presentation?.kind === "changeset" ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.details }) })
|
|
3774
|
+
block.details === void 0 || block.presentation?.kind === "changeset" || toolOutput && !expandedOutput ? null : /* @__PURE__ */ jsx5(Box_default, { paddingLeft: 2, children: /* @__PURE__ */ jsx5(AssistantText, { text: block.details }) })
|
|
3601
3775
|
] });
|
|
3602
3776
|
}
|
|
3603
3777
|
function ToolPresentationView({
|
|
@@ -3606,23 +3780,25 @@ function ToolPresentationView({
|
|
|
3606
3780
|
expandedOutput
|
|
3607
3781
|
}) {
|
|
3608
3782
|
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
|
|
3609
|
-
if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation });
|
|
3783
|
+
if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation, expanded: expandedOutput });
|
|
3610
3784
|
if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation, expanded: expandedOutput });
|
|
3611
3785
|
if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation, expanded: expandedOutput });
|
|
3612
3786
|
if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation, expanded: expandedOutput });
|
|
3613
|
-
return /* @__PURE__ */
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3787
|
+
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, children: [
|
|
3788
|
+
/* @__PURE__ */ jsxs4(Text, { children: [
|
|
3789
|
+
presentation.title,
|
|
3790
|
+
presentation.summary ? ` \xB7 ${presentation.summary}` : ""
|
|
3791
|
+
] }),
|
|
3792
|
+
!expandedOutput || presentation.details === void 0 ? null : /* @__PURE__ */ jsx5(AssistantText, { text: presentation.details })
|
|
3793
|
+
] });
|
|
3617
3794
|
}
|
|
3618
|
-
var CLI_CHANGESET_FILE_LIMIT = 8;
|
|
3619
3795
|
var CHANGESET_TONE = "#b99bf8";
|
|
3620
3796
|
function ChangeSetPresentationView({
|
|
3621
3797
|
presentation,
|
|
3622
3798
|
workspaceName,
|
|
3623
3799
|
expanded
|
|
3624
3800
|
}) {
|
|
3625
|
-
const visibleFiles = expanded ? presentation.files :
|
|
3801
|
+
const visibleFiles = expanded ? presentation.files : [];
|
|
3626
3802
|
const added = presentation.files.reduce((total, file) => total + file.added, 0);
|
|
3627
3803
|
const removed = presentation.files.reduce((total, file) => total + file.removed, 0);
|
|
3628
3804
|
const fileLabel = presentation.files.length === 1 ? "FILE" : "FILES";
|
|
@@ -3689,7 +3865,6 @@ function workspaceRelativePath(value, workspaceName) {
|
|
|
3689
3865
|
if (normalized.toLocaleLowerCase().startsWith(rootPrefix.toLocaleLowerCase())) return normalized.slice(rootPrefix.length);
|
|
3690
3866
|
return normalized;
|
|
3691
3867
|
}
|
|
3692
|
-
var CLI_COMMAND_OUTPUT_LINE_LIMIT = 16;
|
|
3693
3868
|
function CommandPresentationView({
|
|
3694
3869
|
presentation,
|
|
3695
3870
|
expanded
|
|
@@ -3697,9 +3872,7 @@ function CommandPresentationView({
|
|
|
3697
3872
|
const state = presentation.state ?? commandState(presentation.exitCode);
|
|
3698
3873
|
const tone = jobStateColor(state);
|
|
3699
3874
|
const label = presentation.variant === "terminal" ? "TERMINAL" : "COMMAND";
|
|
3700
|
-
const
|
|
3701
|
-
const hasStderr = jobOutputLines(presentation.stderr ?? "").length > 0;
|
|
3702
|
-
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
|
|
3875
|
+
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : 0;
|
|
3703
3876
|
const stdout = boundedCommandLines(presentation.stdout ?? "", perStreamLimit);
|
|
3704
3877
|
const stderr = boundedCommandLines(presentation.stderr ?? "", perStreamLimit);
|
|
3705
3878
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3717,7 +3890,7 @@ function CommandPresentationView({
|
|
|
3717
3890
|
] }),
|
|
3718
3891
|
stdout.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "OUTPUT", value: stdout, tone, error: false }),
|
|
3719
3892
|
stderr.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "ERROR", value: stderr, tone, error: true }),
|
|
3720
|
-
presentation.diagnostic === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3893
|
+
!expanded || presentation.diagnostic === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3721
3894
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
|
|
3722
3895
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: presentation.diagnostic })
|
|
3723
3896
|
] }),
|
|
@@ -3737,7 +3910,8 @@ function CommandOutputSection({
|
|
|
3737
3910
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3738
3911
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u251C\u2500 " }),
|
|
3739
3912
|
/* @__PURE__ */ jsx5(Text, { color: error ? "#e06c50" : tone, bold: true, children: label }),
|
|
3740
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` })
|
|
3913
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.total} ${value.total === 1 ? "LINE" : "LINES"}` }),
|
|
3914
|
+
value.hidden === 0 ? null : /* @__PURE__ */ jsx5(Text, { dimColor: true, children: ` \xB7 ${value.head.length + value.tail.length} SHOWN` })
|
|
3741
3915
|
] }),
|
|
3742
3916
|
value.head.map((line, index) => /* @__PURE__ */ jsx5(CommandOutputLine, { line, tone, error }, `head:${index}`)),
|
|
3743
3917
|
value.hidden === 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3761,9 +3935,10 @@ function CommandOutputLine({ line, tone, error }) {
|
|
|
3761
3935
|
}
|
|
3762
3936
|
function boundedCommandLines(output, limit) {
|
|
3763
3937
|
const lines = jobOutputLines(output);
|
|
3938
|
+
if (limit <= 0) return { total: lines.length, head: [], tail: [], hidden: lines.length };
|
|
3764
3939
|
if (lines.length <= limit) return { total: lines.length, head: lines, tail: [], hidden: 0 };
|
|
3765
|
-
const headCount = Math.ceil(limit
|
|
3766
|
-
const tailCount = Math.
|
|
3940
|
+
const headCount = Math.ceil(limit * 0.625);
|
|
3941
|
+
const tailCount = Math.max(0, limit - headCount);
|
|
3767
3942
|
return {
|
|
3768
3943
|
total: lines.length,
|
|
3769
3944
|
head: lines.slice(0, headCount),
|
|
@@ -3780,7 +3955,6 @@ function commandFooter(presentation, state) {
|
|
|
3780
3955
|
if (presentation.truncated === true) parts.push("output truncated");
|
|
3781
3956
|
return parts.join(" \xB7 ");
|
|
3782
3957
|
}
|
|
3783
|
-
var CLI_WEB_RESULT_LIMIT = 5;
|
|
3784
3958
|
function WebPresentationView({
|
|
3785
3959
|
presentation,
|
|
3786
3960
|
expanded
|
|
@@ -3801,7 +3975,7 @@ function WebPresentationView({
|
|
|
3801
3975
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "Page content added to context" })
|
|
3802
3976
|
] })
|
|
3803
3977
|
] });
|
|
3804
|
-
const visibleItems = expanded ? items :
|
|
3978
|
+
const visibleItems = expanded ? items : [];
|
|
3805
3979
|
const query = presentation.title.replace(/^Search:\s*/iu, "").trim();
|
|
3806
3980
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3807
3981
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3844,8 +4018,6 @@ function compactWebSource(value) {
|
|
|
3844
4018
|
return value;
|
|
3845
4019
|
}
|
|
3846
4020
|
}
|
|
3847
|
-
var CLI_JOB_LOG_LINE_LIMIT = 12;
|
|
3848
|
-
var CLI_JOB_LIST_LIMIT = 8;
|
|
3849
4021
|
function JobPresentationView({
|
|
3850
4022
|
presentation,
|
|
3851
4023
|
expanded
|
|
@@ -3854,7 +4026,7 @@ function JobPresentationView({
|
|
|
3854
4026
|
const state = presentation.state ?? "running";
|
|
3855
4027
|
const tone = jobStateColor(state);
|
|
3856
4028
|
const lines = jobOutputLines(presentation.output ?? "");
|
|
3857
|
-
const visibleLines = expanded ? lines :
|
|
4029
|
+
const visibleLines = expanded ? lines : [];
|
|
3858
4030
|
const hiddenLines = lines.length - visibleLines.length;
|
|
3859
4031
|
const showLog = presentation.action === "read" || presentation.action === "kill" || lines.length > 0;
|
|
3860
4032
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3907,7 +4079,7 @@ function JobListPresentationView({
|
|
|
3907
4079
|
expanded
|
|
3908
4080
|
}) {
|
|
3909
4081
|
const jobs = presentation.jobs ?? [];
|
|
3910
|
-
const visibleJobs = expanded ? jobs :
|
|
4082
|
+
const visibleJobs = expanded ? jobs : [];
|
|
3911
4083
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3912
4084
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3913
4085
|
/* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
|
|
@@ -4259,6 +4431,7 @@ export {
|
|
|
4259
4431
|
boundedCliTurn,
|
|
4260
4432
|
canShowSlashCompletion,
|
|
4261
4433
|
classifyTerminalInput,
|
|
4434
|
+
cliRenderBudget,
|
|
4262
4435
|
cliTranscriptWindow,
|
|
4263
4436
|
closeAndDisposeRuntime,
|
|
4264
4437
|
completionKeyAction,
|
|
@@ -4266,9 +4439,11 @@ export {
|
|
|
4266
4439
|
editPromptWithPastedBlocks,
|
|
4267
4440
|
ideFooterPresentation,
|
|
4268
4441
|
isCopyShortcut,
|
|
4442
|
+
isOutputToggleShortcut,
|
|
4269
4443
|
isPlatformShortcut,
|
|
4270
4444
|
navigateHistory,
|
|
4271
4445
|
navigatePromptHistory,
|
|
4446
|
+
outputToggleShortcut,
|
|
4272
4447
|
pastedDraftPresentation,
|
|
4273
4448
|
prepareCliSubmission,
|
|
4274
4449
|
promptCursorFromClick,
|