flavor-code 1.4.1-beta.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-UKTPW3E6.js → app-4CUS3GEJ.js} +327 -175
- 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,8 +2068,11 @@ 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
|
}
|
|
2000
|
-
function
|
|
2001
|
-
return
|
|
2071
|
+
function isOutputToggleShortcut(character, key) {
|
|
2072
|
+
return key.ctrl && character.toLowerCase() === "o";
|
|
2073
|
+
}
|
|
2074
|
+
function outputToggleShortcut(_platform = process.platform) {
|
|
2075
|
+
return "Ctrl+O";
|
|
2002
2076
|
}
|
|
2003
2077
|
function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
2004
2078
|
if (input.length === 0 && cursor === 0 && images.length > 0) {
|
|
@@ -2006,10 +2080,12 @@ function removeLastCliImageOnBackspace(input, cursor, images) {
|
|
|
2006
2080
|
}
|
|
2007
2081
|
return { handled: false, images: [...images] };
|
|
2008
2082
|
}
|
|
2009
|
-
function prepareCliSubmission(input, images) {
|
|
2083
|
+
function prepareCliSubmission(input, images, slashCommands = MVP_COMMANDS) {
|
|
2010
2084
|
const entered = input.trim();
|
|
2011
2085
|
if (entered.length === 0 && images.length === 0) return { kind: "empty" };
|
|
2012
|
-
|
|
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) {
|
|
2013
2089
|
return { kind: "error", message: "Image attachments cannot be used with slash commands." };
|
|
2014
2090
|
}
|
|
2015
2091
|
const text = entered || "Analyze the attached image(s).";
|
|
@@ -2205,6 +2281,8 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2205
2281
|
pendingPromptRef.current ??= new PendingPromptQueue();
|
|
2206
2282
|
const closing = useRef4(false);
|
|
2207
2283
|
const clipboardBusy = useRef4(false);
|
|
2284
|
+
const clipboardFallbackTimer = useRef4(null);
|
|
2285
|
+
const terminalTextPasteRevision = useRef4(0);
|
|
2208
2286
|
const textBuf = useRef4({ pending: "", timer: null });
|
|
2209
2287
|
const thinkingBuf = useRef4({ pending: "", timer: null });
|
|
2210
2288
|
const promptDraftRef = useRef4({
|
|
@@ -2221,6 +2299,9 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2221
2299
|
const promptHistoryStoreRef = useRef4(void 0);
|
|
2222
2300
|
promptHistoryStoreRef.current ??= new PromptHistoryStore({ home: home ?? homedir(), workspace, maxEntries: HISTORY_CAP });
|
|
2223
2301
|
promptDraftRef.current = { text: input, cursor: promptCursor, pastedBlocks, imageAttachments };
|
|
2302
|
+
useEffect3(() => () => {
|
|
2303
|
+
if (clipboardFallbackTimer.current !== null) clearTimeout(clipboardFallbackTimer.current);
|
|
2304
|
+
}, []);
|
|
2224
2305
|
const commitPromptDraft = (next, recordHistory = true) => {
|
|
2225
2306
|
const current = promptDraftRef.current;
|
|
2226
2307
|
const resolved = {
|
|
@@ -2464,7 +2545,10 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2464
2545
|
setCustomQuestionActive(false);
|
|
2465
2546
|
}, [questions]);
|
|
2466
2547
|
useEffect3(() => setApprovalExpanded(false), [approval?.id]);
|
|
2467
|
-
const derivedSlashCompletion =
|
|
2548
|
+
const derivedSlashCompletion = useMemo3(
|
|
2549
|
+
() => deriveSlashCompletion(input, promptCursor, slashCandidates, slashSelection),
|
|
2550
|
+
[input, promptCursor, slashCandidates, slashSelection]
|
|
2551
|
+
);
|
|
2468
2552
|
const slashCompletion = canShowSlashCompletion(
|
|
2469
2553
|
transcript.active !== void 0,
|
|
2470
2554
|
input,
|
|
@@ -2482,27 +2566,43 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2482
2566
|
setMentionSelection(0);
|
|
2483
2567
|
setDismissedMentionInput(next.text);
|
|
2484
2568
|
};
|
|
2485
|
-
const
|
|
2486
|
-
const active = runtimeRef.current;
|
|
2487
|
-
if (active === void 0) {
|
|
2488
|
-
setClipboardNotice("Flavor is still starting; try pasting the image again.");
|
|
2489
|
-
return;
|
|
2490
|
-
}
|
|
2491
|
-
if (promptDraftRef.current.imageAttachments.length >= DEFAULT_MAX_IMAGES) {
|
|
2492
|
-
setClipboardNotice(`A prompt can contain at most ${DEFAULT_MAX_IMAGES} images.`);
|
|
2493
|
-
return;
|
|
2494
|
-
}
|
|
2569
|
+
const pasteClipboardContent = async (imageOnly = false) => {
|
|
2495
2570
|
if (clipboardBusy.current) return;
|
|
2496
2571
|
clipboardBusy.current = true;
|
|
2497
|
-
|
|
2572
|
+
const pasteRevision = terminalTextPasteRevision.current;
|
|
2573
|
+
setClipboardNotice(imageOnly ? "Reading clipboard image..." : "Reading clipboard...");
|
|
2498
2574
|
try {
|
|
2499
|
-
const
|
|
2500
|
-
if (
|
|
2501
|
-
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.");
|
|
2502
2597
|
return;
|
|
2503
2598
|
}
|
|
2504
|
-
const incomingBytes = Buffer.byteLength(attachment.dataBase64, "base64");
|
|
2505
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");
|
|
2506
2606
|
const currentBytes = currentDraft.imageAttachments.reduce((sum, image) => sum + image.bytes, 0);
|
|
2507
2607
|
if (currentBytes + incomingBytes > DEFAULT_MAX_TOTAL_IMAGE_BYTES) {
|
|
2508
2608
|
throw new Error(`Image attachments exceed the maximum total size of ${DEFAULT_MAX_TOTAL_IMAGE_BYTES} bytes`);
|
|
@@ -2542,7 +2642,7 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2542
2642
|
}
|
|
2543
2643
|
const active = runtimeRef.current;
|
|
2544
2644
|
if (isCopyShortcut(character, key)) {
|
|
2545
|
-
if (selection.hasSelection()) selection.
|
|
2645
|
+
if (selection.hasSelection()) selection.copySelectionNoClear();
|
|
2546
2646
|
else if (process.platform !== "darwin") interrupt();
|
|
2547
2647
|
return;
|
|
2548
2648
|
}
|
|
@@ -2550,12 +2650,30 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2550
2650
|
interrupt();
|
|
2551
2651
|
return;
|
|
2552
2652
|
}
|
|
2553
|
-
if (
|
|
2653
|
+
if (isOutputToggleShortcut(character, key)) {
|
|
2554
2654
|
setExpandedOutput((value) => !value);
|
|
2555
2655
|
return;
|
|
2556
2656
|
}
|
|
2557
|
-
if (
|
|
2558
|
-
|
|
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);
|
|
2559
2677
|
return;
|
|
2560
2678
|
}
|
|
2561
2679
|
if (active?.approvals.pending !== void 0) {
|
|
@@ -2713,8 +2831,19 @@ function App({ workspace, home, resumeSession, instanceId, palAlias }) {
|
|
|
2713
2831
|
return;
|
|
2714
2832
|
}
|
|
2715
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
|
+
}
|
|
2716
2845
|
const images = [...imageAttachments];
|
|
2717
|
-
const prepared = prepareCliSubmission(input, images);
|
|
2846
|
+
const prepared = prepareCliSubmission(input, images, slashCandidates.map(({ name }) => name));
|
|
2718
2847
|
if (prepared.kind === "empty" || active === void 0) return;
|
|
2719
2848
|
if (prepared.kind === "error") {
|
|
2720
2849
|
setClipboardNotice(prepared.message);
|
|
@@ -2921,6 +3050,25 @@ var CLI_VISIBLE_TURN_LIMIT = 40;
|
|
|
2921
3050
|
var CLI_VISIBLE_BLOCK_LIMIT = 320;
|
|
2922
3051
|
var CLI_VISIBLE_BLOCKS_PER_TURN = 80;
|
|
2923
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
|
+
}
|
|
2924
3072
|
function approvalDetailLines(approval) {
|
|
2925
3073
|
const lines = [];
|
|
2926
3074
|
if (approval.agent !== "main") lines.push(`Agent: ${approval.agent}`);
|
|
@@ -2970,25 +3118,32 @@ function boundedCliDisplayText(text, limit = CLI_VISIBLE_TEXT_CHARS) {
|
|
|
2970
3118
|
|
|
2971
3119
|
${text.slice(-half)}`;
|
|
2972
3120
|
}
|
|
2973
|
-
function boundedCliPresentation(presentation) {
|
|
3121
|
+
function boundedCliPresentation(presentation, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
|
|
2974
3122
|
if (presentation.kind === "terminal") return {
|
|
2975
3123
|
...presentation,
|
|
2976
|
-
...presentation.stdout === void 0 ? {} : { stdout: boundedCliDisplayText(presentation.stdout) },
|
|
2977
|
-
...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) }
|
|
2978
3126
|
};
|
|
2979
3127
|
if (presentation.kind === "job" && presentation.output !== void 0) return {
|
|
2980
3128
|
...presentation,
|
|
2981
|
-
output: boundedCliDisplayText(presentation.output)
|
|
3129
|
+
output: boundedCliDisplayText(presentation.output, maxTextChars)
|
|
2982
3130
|
};
|
|
2983
3131
|
return presentation;
|
|
2984
3132
|
}
|
|
2985
|
-
function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN) {
|
|
3133
|
+
function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN, maxTextChars = CLI_VISIBLE_TEXT_CHARS) {
|
|
2986
3134
|
const blockLimit = Math.max(1, Math.floor(maxBlocks));
|
|
2987
3135
|
const hiddenBlocks = Math.max(0, turn.blocks.length - blockLimit);
|
|
2988
|
-
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) } : {
|
|
2989
3137
|
...block,
|
|
2990
|
-
...block.details === void 0 ? {} : {
|
|
2991
|
-
|
|
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
|
+
}
|
|
2992
3147
|
});
|
|
2993
3148
|
const blocks = hiddenBlocks === 0 ? visible : [{
|
|
2994
3149
|
kind: "status",
|
|
@@ -3006,7 +3161,7 @@ function boundedCliTurn(turn, maxBlocks = CLI_VISIBLE_BLOCKS_PER_TURN) {
|
|
|
3006
3161
|
}
|
|
3007
3162
|
};
|
|
3008
3163
|
}
|
|
3009
|
-
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) {
|
|
3010
3165
|
const turns = [];
|
|
3011
3166
|
let remainingBlocks = Math.max(1, Math.floor(maxBlocks));
|
|
3012
3167
|
let hiddenBlocks = 0;
|
|
@@ -3014,7 +3169,7 @@ function cliTranscriptWindow(completed, maxTurns = CLI_VISIBLE_TURN_LIMIT, maxBl
|
|
|
3014
3169
|
const source = completed[index];
|
|
3015
3170
|
if (remainingBlocks <= 0) break;
|
|
3016
3171
|
const allowance = Math.min(CLI_VISIBLE_BLOCKS_PER_TURN, remainingBlocks);
|
|
3017
|
-
const bounded = boundedCliTurn(source, allowance);
|
|
3172
|
+
const bounded = boundedCliTurn(source, allowance, maxTextChars);
|
|
3018
3173
|
turns.push(bounded.turn);
|
|
3019
3174
|
hiddenBlocks += bounded.hiddenBlocks;
|
|
3020
3175
|
remainingBlocks -= Math.min(source.blocks.length, allowance);
|
|
@@ -3063,23 +3218,29 @@ function TerminalLayout({
|
|
|
3063
3218
|
const dividerWidth = Math.max(1, columns - 1);
|
|
3064
3219
|
const outputShortcut = outputToggleShortcut();
|
|
3065
3220
|
const showWelcome = completed.length === 0 && active === void 0;
|
|
3066
|
-
const
|
|
3067
|
-
|
|
3068
|
-
|
|
3221
|
+
const budget = useMemo3(
|
|
3222
|
+
() => cliRenderBudget(rows, columns),
|
|
3223
|
+
[rows, columns]
|
|
3224
|
+
);
|
|
3225
|
+
const activeTaskBlocks = useMemo3(() => active?.blocks.filter(
|
|
3069
3226
|
(block) => block.kind === "status" && block.task !== void 0
|
|
3070
|
-
) ?? [];
|
|
3071
|
-
const
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
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
|
+
);
|
|
3079
3240
|
const questionRows = questions === void 0 ? 0 : 4 + (questions[questionIndex]?.options.length ?? 0) + questions.length * 2;
|
|
3080
3241
|
const memoryReviewRows = memoryReviews.length === 0 ? 0 : 5;
|
|
3081
3242
|
const approvalRows = approval === void 0 ? 0 : 3 + (approvalExpanded ? approvalDetailLines(approval).length : 0);
|
|
3082
|
-
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows +
|
|
3243
|
+
const fixedBottomRows = approvalRows + questionRows + memoryReviewRows + (pendingPrompts.length === 0 ? 0 : 1) + imageAttachments.length + (clipboardNotice === void 0 ? 0 : 1) + 2;
|
|
3083
3244
|
const taskPanelRows = taskPanelViewportRows(rows, fixedBottomRows, activeTaskBlocks.length > 0);
|
|
3084
3245
|
const availableBottomRows = Math.max(1, rows - taskPanelRows - 1);
|
|
3085
3246
|
const bottomMaxRows = Math.min(availableBottomRows, Math.max(Math.floor(rows / 2), fixedBottomRows + 1));
|
|
@@ -3098,9 +3259,7 @@ function TerminalLayout({
|
|
|
3098
3259
|
completedWindow.hiddenTurns,
|
|
3099
3260
|
" earlier turns and ",
|
|
3100
3261
|
completedWindow.hiddenBlocks,
|
|
3101
|
-
" output items hidden
|
|
3102
|
-
outputShortcut,
|
|
3103
|
-
" expand all"
|
|
3262
|
+
" output items hidden to keep the terminal responsive"
|
|
3104
3263
|
] }) : null,
|
|
3105
3264
|
completedWindow.turns.map((turn, index) => /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3106
3265
|
index > 0 ? /* @__PURE__ */ jsx5(TurnSeparator, { width: columns }) : null,
|
|
@@ -3123,82 +3282,86 @@ function TerminalLayout({
|
|
|
3123
3282
|
...onTaskPanelHoverChange === void 0 ? {} : { onHoverChange: onTaskPanelHoverChange }
|
|
3124
3283
|
}
|
|
3125
3284
|
),
|
|
3126
|
-
/* @__PURE__ */ jsxs4(Box_default, {
|
|
3127
|
-
|
|
3128
|
-
/* @__PURE__ */
|
|
3129
|
-
|
|
3130
|
-
|
|
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
|
+
] })
|
|
3131
3327
|
] }),
|
|
3132
|
-
/* @__PURE__ */
|
|
3133
|
-
|
|
3134
|
-
|
|
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"
|
|
3135
3336
|
] }),
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
] })
|
|
3164
|
-
!questions || questions.length === 0 ? null : /* @__PURE__ */ jsx5(QuestionCards, { questions, activeIndex: questionIndex, answers: questionAnswers, customActive: customQuestionActive }),
|
|
3165
|
-
memoryReviews.length === 0 ? null : /* @__PURE__ */ jsx5(MemoryReviewCards, { reviews: memoryReviews, autoDismissSeconds: memoryAutoDismissSeconds }),
|
|
3166
|
-
completion === void 0 ? null : /* @__PURE__ */ jsx5(SlashMenu, { completion }),
|
|
3167
|
-
mentionCompletion === void 0 ? null : /* @__PURE__ */ jsx5(MentionMenu, { completion: mentionCompletion, ...onMentionSelect === void 0 ? {} : { onSelect: onMentionSelect } }),
|
|
3168
|
-
pendingPrompts.length === 0 ? null : /* @__PURE__ */ jsxs4(Text, { color: "yellow", wrap: "truncate-end", children: [
|
|
3169
|
-
"Pending (",
|
|
3170
|
-
pendingPrompts.length,
|
|
3171
|
-
") \xB7 ",
|
|
3172
|
-
queuedPromptLabel(pendingPrompts.at(-1)),
|
|
3173
|
-
" \xB7 Esc edit latest"
|
|
3174
|
-
] }),
|
|
3175
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(dividerWidth) }),
|
|
3176
|
-
imageAttachments.map((image, index) => /* @__PURE__ */ jsxs4(Text, { color: "cyan", wrap: "truncate-end", children: [
|
|
3177
|
-
"[Image #",
|
|
3178
|
-
index + 1,
|
|
3179
|
-
"] ",
|
|
3180
|
-
image.name ?? basename3(image.source.path)
|
|
3181
|
-
] }, `${image.sha256}:${index}`)),
|
|
3182
|
-
clipboardNotice === void 0 ? null : /* @__PURE__ */ jsx5(Text, { color: "yellow", wrap: "truncate-end", children: clipboardNotice }),
|
|
3183
|
-
/* @__PURE__ */ jsx5(
|
|
3184
|
-
PromptLine,
|
|
3185
|
-
{
|
|
3186
|
-
input,
|
|
3187
|
-
pastedBlocks,
|
|
3188
|
-
cursor: promptCursor,
|
|
3189
|
-
columns,
|
|
3190
|
-
maxVisibleLines: promptMaxLines,
|
|
3191
|
-
completedSlashTokenLength: tokenLength,
|
|
3192
|
-
...onPromptCursorChange === void 0 ? {} : { onCursorChange: onPromptCursorChange }
|
|
3193
|
-
}
|
|
3194
|
-
),
|
|
3195
|
-
/* @__PURE__ */ jsx5(
|
|
3196
|
-
FooterStatus,
|
|
3197
|
-
{
|
|
3198
|
-
hint: 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"} 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 ${outputShortcut} ${expandedOutput ? "collapse" : "expand"} output \xB7 Ctrl+C exit`,
|
|
3199
|
-
...ideContext === void 0 ? {} : { ideContext }
|
|
3200
|
-
}
|
|
3201
|
-
)
|
|
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
|
+
] })
|
|
3202
3365
|
] })
|
|
3203
3366
|
] });
|
|
3204
3367
|
}
|
|
@@ -3300,7 +3463,7 @@ function SlashMenu({ completion }) {
|
|
|
3300
3463
|
presentation.marker,
|
|
3301
3464
|
/* @__PURE__ */ jsx5(HighlightedName, { name: candidate.name, query: completion.query, matchStyle: presentation.matchStyle }),
|
|
3302
3465
|
candidate.kind === "skill" || candidate.kind === "plugin" ? /* @__PURE__ */ jsx5(Text, { color: candidate.kind === "skill" ? "magentaBright" : "cyanBright", children: ` ${candidate.kind}` }) : null,
|
|
3303
|
-
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)}` })
|
|
3304
3467
|
] }, `${candidate.kind}:${candidate.name}`);
|
|
3305
3468
|
}) });
|
|
3306
3469
|
}
|
|
@@ -3379,7 +3542,7 @@ function scrollUp(scroll, amount) {
|
|
|
3379
3542
|
function TurnSeparator({ width }) {
|
|
3380
3543
|
return /* @__PURE__ */ jsx5(Text, { dimColor: true, children: "\u2500".repeat(Math.max(1, width - 1)) });
|
|
3381
3544
|
}
|
|
3382
|
-
|
|
3545
|
+
var TurnView = React4.memo(function TurnView2({
|
|
3383
3546
|
turn,
|
|
3384
3547
|
interactive,
|
|
3385
3548
|
workspaceName,
|
|
@@ -3418,11 +3581,11 @@ function TurnView({
|
|
|
3418
3581
|
] }),
|
|
3419
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}`)) })
|
|
3420
3583
|
] });
|
|
3421
|
-
}
|
|
3584
|
+
});
|
|
3422
3585
|
var DIFF_CONTENT = fileDiffLineStyle("context").contentColor;
|
|
3423
3586
|
var DIFF_REMOVED_MARKER = fileDiffLineStyle("removed").markerColor;
|
|
3424
3587
|
var DIFF_ADDED_MARKER = fileDiffLineStyle("added").markerColor;
|
|
3425
|
-
function FileDiffView({ presentation }) {
|
|
3588
|
+
function FileDiffView({ presentation, expanded }) {
|
|
3426
3589
|
const operation = presentation.operation === "create" ? "Create" : presentation.operation === "delete" ? "Delete" : "Update";
|
|
3427
3590
|
if (presentation.operation === "delete") {
|
|
3428
3591
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "row", children: [
|
|
@@ -3454,7 +3617,7 @@ function FileDiffView({ presentation }) {
|
|
|
3454
3617
|
", removed ",
|
|
3455
3618
|
lineCount(presentation.removed)
|
|
3456
3619
|
] }),
|
|
3457
|
-
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}`))
|
|
3458
3621
|
] });
|
|
3459
3622
|
}
|
|
3460
3623
|
function FileDiffRow({ line, lineWidth }) {
|
|
@@ -3600,6 +3763,7 @@ function StatusBlockView({
|
|
|
3600
3763
|
}) {
|
|
3601
3764
|
const visibleBlock = cliToolTitle(block);
|
|
3602
3765
|
const outcome = cliToolOutcome(block);
|
|
3766
|
+
const toolOutput = block.tool !== void 0 || block.presentation !== void 0;
|
|
3603
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 });
|
|
3604
3768
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", children: [
|
|
3605
3769
|
primary,
|
|
@@ -3607,7 +3771,7 @@ function StatusBlockView({
|
|
|
3607
3771
|
"\u2514 ",
|
|
3608
3772
|
outcome
|
|
3609
3773
|
] }) }),
|
|
3610
|
-
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 }) })
|
|
3611
3775
|
] });
|
|
3612
3776
|
}
|
|
3613
3777
|
function ToolPresentationView({
|
|
@@ -3616,23 +3780,25 @@ function ToolPresentationView({
|
|
|
3616
3780
|
expandedOutput
|
|
3617
3781
|
}) {
|
|
3618
3782
|
if (presentation.kind === "changeset") return /* @__PURE__ */ jsx5(ChangeSetPresentationView, { presentation, workspaceName, expanded: expandedOutput });
|
|
3619
|
-
if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation });
|
|
3783
|
+
if (presentation.kind === "file-change") return /* @__PURE__ */ jsx5(FileDiffView, { presentation, expanded: expandedOutput });
|
|
3620
3784
|
if (presentation.kind === "terminal") return /* @__PURE__ */ jsx5(CommandPresentationView, { presentation, expanded: expandedOutput });
|
|
3621
3785
|
if (presentation.kind === "web") return /* @__PURE__ */ jsx5(WebPresentationView, { presentation, expanded: expandedOutput });
|
|
3622
3786
|
if (presentation.kind === "job") return /* @__PURE__ */ jsx5(JobPresentationView, { presentation, expanded: expandedOutput });
|
|
3623
|
-
return /* @__PURE__ */
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
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
|
+
] });
|
|
3627
3794
|
}
|
|
3628
|
-
var CLI_CHANGESET_FILE_LIMIT = 8;
|
|
3629
3795
|
var CHANGESET_TONE = "#b99bf8";
|
|
3630
3796
|
function ChangeSetPresentationView({
|
|
3631
3797
|
presentation,
|
|
3632
3798
|
workspaceName,
|
|
3633
3799
|
expanded
|
|
3634
3800
|
}) {
|
|
3635
|
-
const visibleFiles = expanded ? presentation.files :
|
|
3801
|
+
const visibleFiles = expanded ? presentation.files : [];
|
|
3636
3802
|
const added = presentation.files.reduce((total, file) => total + file.added, 0);
|
|
3637
3803
|
const removed = presentation.files.reduce((total, file) => total + file.removed, 0);
|
|
3638
3804
|
const fileLabel = presentation.files.length === 1 ? "FILE" : "FILES";
|
|
@@ -3699,7 +3865,6 @@ function workspaceRelativePath(value, workspaceName) {
|
|
|
3699
3865
|
if (normalized.toLocaleLowerCase().startsWith(rootPrefix.toLocaleLowerCase())) return normalized.slice(rootPrefix.length);
|
|
3700
3866
|
return normalized;
|
|
3701
3867
|
}
|
|
3702
|
-
var CLI_COMMAND_OUTPUT_LINE_LIMIT = 8;
|
|
3703
3868
|
function CommandPresentationView({
|
|
3704
3869
|
presentation,
|
|
3705
3870
|
expanded
|
|
@@ -3707,14 +3872,9 @@ function CommandPresentationView({
|
|
|
3707
3872
|
const state = presentation.state ?? commandState(presentation.exitCode);
|
|
3708
3873
|
const tone = jobStateColor(state);
|
|
3709
3874
|
const label = presentation.variant === "terminal" ? "TERMINAL" : "COMMAND";
|
|
3710
|
-
const
|
|
3711
|
-
const hasStderr = jobOutputLines(presentation.stderr ?? "").length > 0;
|
|
3712
|
-
const collapsedPerStreamLimit = hasStdout && hasStderr ? Math.floor(CLI_COMMAND_OUTPUT_LINE_LIMIT / 2) : CLI_COMMAND_OUTPUT_LINE_LIMIT;
|
|
3713
|
-
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : collapsedPerStreamLimit;
|
|
3875
|
+
const perStreamLimit = expanded ? Number.POSITIVE_INFINITY : 0;
|
|
3714
3876
|
const stdout = boundedCommandLines(presentation.stdout ?? "", perStreamLimit);
|
|
3715
3877
|
const stderr = boundedCommandLines(presentation.stderr ?? "", perStreamLimit);
|
|
3716
|
-
const collapsible = stdout.total > collapsedPerStreamLimit || stderr.total > collapsedPerStreamLimit;
|
|
3717
|
-
const shortcut = outputToggleShortcut();
|
|
3718
3878
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3719
3879
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3720
3880
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u250C\u2500 " }),
|
|
@@ -3730,21 +3890,13 @@ function CommandPresentationView({
|
|
|
3730
3890
|
] }),
|
|
3731
3891
|
stdout.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "OUTPUT", value: stdout, tone, error: false }),
|
|
3732
3892
|
stderr.total === 0 ? null : /* @__PURE__ */ jsx5(CommandOutputSection, { label: "ERROR", value: stderr, tone, error: true }),
|
|
3733
|
-
presentation.diagnostic === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3893
|
+
!expanded || presentation.diagnostic === void 0 ? null : /* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3734
3894
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2502 " }),
|
|
3735
3895
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: presentation.diagnostic })
|
|
3736
3896
|
] }),
|
|
3737
3897
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3738
3898
|
/* @__PURE__ */ jsx5(Text, { color: tone, children: "\u2514\u2500 " }),
|
|
3739
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: commandFooter(presentation, state) })
|
|
3740
|
-
collapsible ? /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
3741
|
-
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: " \xB7 " }),
|
|
3742
|
-
/* @__PURE__ */ jsx5(Text, { color: "ansi:cyanBright", children: shortcut }),
|
|
3743
|
-
/* @__PURE__ */ jsxs4(Text, { dimColor: true, children: [
|
|
3744
|
-
" ",
|
|
3745
|
-
expanded ? "collapse" : "expand"
|
|
3746
|
-
] })
|
|
3747
|
-
] }) : null
|
|
3899
|
+
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: commandFooter(presentation, state) })
|
|
3748
3900
|
] })
|
|
3749
3901
|
] });
|
|
3750
3902
|
}
|
|
@@ -3783,6 +3935,7 @@ function CommandOutputLine({ line, tone, error }) {
|
|
|
3783
3935
|
}
|
|
3784
3936
|
function boundedCommandLines(output, limit) {
|
|
3785
3937
|
const lines = jobOutputLines(output);
|
|
3938
|
+
if (limit <= 0) return { total: lines.length, head: [], tail: [], hidden: lines.length };
|
|
3786
3939
|
if (lines.length <= limit) return { total: lines.length, head: lines, tail: [], hidden: 0 };
|
|
3787
3940
|
const headCount = Math.ceil(limit * 0.625);
|
|
3788
3941
|
const tailCount = Math.max(0, limit - headCount);
|
|
@@ -3802,7 +3955,6 @@ function commandFooter(presentation, state) {
|
|
|
3802
3955
|
if (presentation.truncated === true) parts.push("output truncated");
|
|
3803
3956
|
return parts.join(" \xB7 ");
|
|
3804
3957
|
}
|
|
3805
|
-
var CLI_WEB_RESULT_LIMIT = 5;
|
|
3806
3958
|
function WebPresentationView({
|
|
3807
3959
|
presentation,
|
|
3808
3960
|
expanded
|
|
@@ -3823,7 +3975,7 @@ function WebPresentationView({
|
|
|
3823
3975
|
/* @__PURE__ */ jsx5(Text, { dimColor: true, children: "Page content added to context" })
|
|
3824
3976
|
] })
|
|
3825
3977
|
] });
|
|
3826
|
-
const visibleItems = expanded ? items :
|
|
3978
|
+
const visibleItems = expanded ? items : [];
|
|
3827
3979
|
const query = presentation.title.replace(/^Search:\s*/iu, "").trim();
|
|
3828
3980
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3829
3981
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
@@ -3866,8 +4018,6 @@ function compactWebSource(value) {
|
|
|
3866
4018
|
return value;
|
|
3867
4019
|
}
|
|
3868
4020
|
}
|
|
3869
|
-
var CLI_JOB_LOG_LINE_LIMIT = 12;
|
|
3870
|
-
var CLI_JOB_LIST_LIMIT = 8;
|
|
3871
4021
|
function JobPresentationView({
|
|
3872
4022
|
presentation,
|
|
3873
4023
|
expanded
|
|
@@ -3876,7 +4026,7 @@ function JobPresentationView({
|
|
|
3876
4026
|
const state = presentation.state ?? "running";
|
|
3877
4027
|
const tone = jobStateColor(state);
|
|
3878
4028
|
const lines = jobOutputLines(presentation.output ?? "");
|
|
3879
|
-
const visibleLines = expanded ? lines :
|
|
4029
|
+
const visibleLines = expanded ? lines : [];
|
|
3880
4030
|
const hiddenLines = lines.length - visibleLines.length;
|
|
3881
4031
|
const showLog = presentation.action === "read" || presentation.action === "kill" || lines.length > 0;
|
|
3882
4032
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
@@ -3929,7 +4079,7 @@ function JobListPresentationView({
|
|
|
3929
4079
|
expanded
|
|
3930
4080
|
}) {
|
|
3931
4081
|
const jobs = presentation.jobs ?? [];
|
|
3932
|
-
const visibleJobs = expanded ? jobs :
|
|
4082
|
+
const visibleJobs = expanded ? jobs : [];
|
|
3933
4083
|
return /* @__PURE__ */ jsxs4(Box_default, { flexDirection: "column", paddingLeft: 2, marginBottom: 1, children: [
|
|
3934
4084
|
/* @__PURE__ */ jsxs4(Box_default, { children: [
|
|
3935
4085
|
/* @__PURE__ */ jsx5(Text, { color: "#d7a657", children: "\u250C\u2500 " }),
|
|
@@ -4281,6 +4431,7 @@ export {
|
|
|
4281
4431
|
boundedCliTurn,
|
|
4282
4432
|
canShowSlashCompletion,
|
|
4283
4433
|
classifyTerminalInput,
|
|
4434
|
+
cliRenderBudget,
|
|
4284
4435
|
cliTranscriptWindow,
|
|
4285
4436
|
closeAndDisposeRuntime,
|
|
4286
4437
|
completionKeyAction,
|
|
@@ -4288,6 +4439,7 @@ export {
|
|
|
4288
4439
|
editPromptWithPastedBlocks,
|
|
4289
4440
|
ideFooterPresentation,
|
|
4290
4441
|
isCopyShortcut,
|
|
4442
|
+
isOutputToggleShortcut,
|
|
4291
4443
|
isPlatformShortcut,
|
|
4292
4444
|
navigateHistory,
|
|
4293
4445
|
navigatePromptHistory,
|