fluxflow-cli 2.13.4 → 2.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluxflow.js +2144 -1372
- package/package.json +2 -2
package/dist/fluxflow.js
CHANGED
|
@@ -40,6 +40,7 @@ __export(paths_exports, {
|
|
|
40
40
|
CONTEXT_FILE: () => CONTEXT_FILE,
|
|
41
41
|
DATA_DIR: () => DATA_DIR,
|
|
42
42
|
FLUXFLOW_DIR: () => FLUXFLOW_DIR,
|
|
43
|
+
HISTORY_DIR: () => HISTORY_DIR,
|
|
43
44
|
HISTORY_FILE: () => HISTORY_FILE,
|
|
44
45
|
LEDGER_FILE: () => LEDGER_FILE,
|
|
45
46
|
LOGS_DIR: () => LOGS_DIR,
|
|
@@ -56,7 +57,7 @@ import os from "os";
|
|
|
56
57
|
import path from "path";
|
|
57
58
|
import fs from "fs";
|
|
58
59
|
import crypto from "crypto";
|
|
59
|
-
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
60
|
+
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
60
61
|
var init_paths = __esm({
|
|
61
62
|
"src/utils/paths.js"() {
|
|
62
63
|
FLUXFLOW_DIR = path.join(os.homedir(), ".fluxflow");
|
|
@@ -93,6 +94,7 @@ var init_paths = __esm({
|
|
|
93
94
|
LOGS_DIR = path.join(DATA_DIR, "logs");
|
|
94
95
|
SECRET_DIR = path.join(DATA_DIR, "secret");
|
|
95
96
|
HISTORY_FILE = path.join(SECRET_DIR, "history.json");
|
|
97
|
+
HISTORY_DIR = path.join(SECRET_DIR, "history");
|
|
96
98
|
USAGE_FILE = path.join(FLUXFLOW_DIR, "usage.json");
|
|
97
99
|
MEMORIES_FILE = path.join(SECRET_DIR, "memories.json");
|
|
98
100
|
TEMP_MEM_FILE = path.join(SECRET_DIR, "memory-temp.json");
|
|
@@ -114,7 +116,7 @@ var XOR_KEY, bypass, xorTransform, AES_ALGORITHM, AES_KEY, encryptAes, decryptAe
|
|
|
114
116
|
var init_crypto = __esm({
|
|
115
117
|
"src/utils/crypto.js"() {
|
|
116
118
|
XOR_KEY = 66;
|
|
117
|
-
bypass =
|
|
119
|
+
bypass = true;
|
|
118
120
|
xorTransform = (data) => {
|
|
119
121
|
const buffer = Buffer.isBuffer(data) ? data : Buffer.from(data);
|
|
120
122
|
const result = Buffer.alloc(buffer.length);
|
|
@@ -2087,329 +2089,9 @@ var init_build = __esm({
|
|
|
2087
2089
|
}
|
|
2088
2090
|
});
|
|
2089
2091
|
|
|
2090
|
-
// src/components/MultilineInput.jsx
|
|
2091
|
-
import React2, { useState as useState2, useEffect as useEffect2, useMemo, useCallback, useRef } from "react";
|
|
2092
|
-
import { Box, Text as Text2, useInput } from "ink";
|
|
2093
|
-
function expandTabs(text, tabSize) {
|
|
2094
|
-
return text.replace(/\t/g, " ".repeat(tabSize));
|
|
2095
|
-
}
|
|
2096
|
-
function normalizeLineEndings(text) {
|
|
2097
|
-
if (text == null) return "";
|
|
2098
|
-
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2099
|
-
}
|
|
2100
|
-
function computeVisualMatrix(value, cursorIndex, wrapWidth, formatText) {
|
|
2101
|
-
const textBefore = (value || "").slice(0, cursorIndex);
|
|
2102
|
-
const visualCursorIdx = formatText(textBefore).length;
|
|
2103
|
-
const fullFormatted = formatText(value || "");
|
|
2104
|
-
const literalLines = fullFormatted.split("\n");
|
|
2105
|
-
const visualLines = [];
|
|
2106
|
-
let currentIdx = 0;
|
|
2107
|
-
let cursorLine = 0;
|
|
2108
|
-
let cursorCol = 0;
|
|
2109
|
-
let foundCursor = false;
|
|
2110
|
-
for (let i = 0; i < literalLines.length; i++) {
|
|
2111
|
-
const line = literalLines[i];
|
|
2112
|
-
if (line.length === 0) {
|
|
2113
|
-
if (!foundCursor && visualCursorIdx === currentIdx) {
|
|
2114
|
-
cursorLine = visualLines.length;
|
|
2115
|
-
cursorCol = 0;
|
|
2116
|
-
foundCursor = true;
|
|
2117
|
-
}
|
|
2118
|
-
visualLines.push({ text: "", globalStart: currentIdx });
|
|
2119
|
-
currentIdx += 1;
|
|
2120
|
-
continue;
|
|
2121
|
-
}
|
|
2122
|
-
for (let j = 0; j < line.length; j += wrapWidth) {
|
|
2123
|
-
const chunk = line.slice(j, j + wrapWidth);
|
|
2124
|
-
const chunkStart = currentIdx + j;
|
|
2125
|
-
const chunkEnd = chunkStart + chunk.length;
|
|
2126
|
-
if (!foundCursor && visualCursorIdx >= chunkStart && (visualCursorIdx < chunkEnd || visualCursorIdx === chunkEnd && j + wrapWidth >= line.length && i === literalLines.length - 1)) {
|
|
2127
|
-
cursorLine = visualLines.length;
|
|
2128
|
-
cursorCol = visualCursorIdx - chunkStart;
|
|
2129
|
-
foundCursor = true;
|
|
2130
|
-
}
|
|
2131
|
-
visualLines.push({ text: chunk, globalStart: chunkStart });
|
|
2132
|
-
}
|
|
2133
|
-
currentIdx += line.length + 1;
|
|
2134
|
-
}
|
|
2135
|
-
if (!foundCursor) {
|
|
2136
|
-
if (visualLines.length === 0) {
|
|
2137
|
-
visualLines.push({ text: "", globalStart: 0 });
|
|
2138
|
-
} else {
|
|
2139
|
-
if (fullFormatted.endsWith("\n")) {
|
|
2140
|
-
visualLines.push({ text: "", globalStart: currentIdx });
|
|
2141
|
-
cursorLine = visualLines.length - 1;
|
|
2142
|
-
cursorCol = 0;
|
|
2143
|
-
} else {
|
|
2144
|
-
cursorLine = visualLines.length - 1;
|
|
2145
|
-
cursorCol = visualLines[cursorLine].text.length;
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
return { visualLines, cursorLine, cursorCol };
|
|
2150
|
-
}
|
|
2151
|
-
var ControlledMultilineInput, MultilineInput;
|
|
2152
|
-
var init_MultilineInput = __esm({
|
|
2153
|
-
"src/components/MultilineInput.jsx"() {
|
|
2154
|
-
ControlledMultilineInput = ({
|
|
2155
|
-
value,
|
|
2156
|
-
rows,
|
|
2157
|
-
maxRows,
|
|
2158
|
-
highlightStyle,
|
|
2159
|
-
textStyle,
|
|
2160
|
-
placeholder = "",
|
|
2161
|
-
mask,
|
|
2162
|
-
showCursor = true,
|
|
2163
|
-
focus = true,
|
|
2164
|
-
tabSize = 4,
|
|
2165
|
-
cursorIndex = 0,
|
|
2166
|
-
highlight,
|
|
2167
|
-
columns = 80
|
|
2168
|
-
}) => {
|
|
2169
|
-
const scrollOffsetRef = useRef(0);
|
|
2170
|
-
const wrapWidth = useMemo(() => Math.max(20, columns - 10), [columns]);
|
|
2171
|
-
const formatText = useCallback(
|
|
2172
|
-
(text, isPlaceholder = false) => {
|
|
2173
|
-
const normalized = normalizeLineEndings(text);
|
|
2174
|
-
if (!isPlaceholder && mask) {
|
|
2175
|
-
return normalized.replace(/[^\n]/g, mask);
|
|
2176
|
-
}
|
|
2177
|
-
const expanded = expandTabs(normalized, tabSize);
|
|
2178
|
-
if (isPlaceholder) return expanded;
|
|
2179
|
-
return expanded.replace(/@\[(.*?)\]/g, (match, p1) => {
|
|
2180
|
-
const hashIdx = p1.indexOf("#");
|
|
2181
|
-
const colonIdx = p1.indexOf(":L");
|
|
2182
|
-
let pathOnly = p1;
|
|
2183
|
-
let suffix = "";
|
|
2184
|
-
if (hashIdx !== -1) {
|
|
2185
|
-
pathOnly = p1.slice(0, hashIdx);
|
|
2186
|
-
suffix = p1.slice(hashIdx);
|
|
2187
|
-
} else if (colonIdx !== -1) {
|
|
2188
|
-
pathOnly = p1.slice(0, colonIdx);
|
|
2189
|
-
suffix = p1.slice(colonIdx);
|
|
2190
|
-
}
|
|
2191
|
-
let rel = pathOnly.replace(/\\/g, "/");
|
|
2192
|
-
const cwd = (process.cwd() || "").replace(/\\/g, "/");
|
|
2193
|
-
if (cwd && rel.toLowerCase().startsWith(cwd.toLowerCase() + "/")) {
|
|
2194
|
-
rel = rel.slice(cwd.length + 1);
|
|
2195
|
-
} else if (rel.startsWith("./")) {
|
|
2196
|
-
rel = rel.slice(2);
|
|
2197
|
-
}
|
|
2198
|
-
const parts = rel.split("/");
|
|
2199
|
-
const basename = parts[parts.length - 1];
|
|
2200
|
-
return `[${basename}${suffix}]`;
|
|
2201
|
-
});
|
|
2202
|
-
},
|
|
2203
|
-
[tabSize, mask]
|
|
2204
|
-
);
|
|
2205
|
-
const { visualLines, cursorLine, cursorCol } = useMemo(() => {
|
|
2206
|
-
return computeVisualMatrix(value, cursorIndex, wrapWidth, formatText);
|
|
2207
|
-
}, [value, cursorIndex, wrapWidth, formatText]);
|
|
2208
|
-
const contentHeight = visualLines.length;
|
|
2209
|
-
const visibleRows = useMemo(() => {
|
|
2210
|
-
return Math.max(rows ?? maxRows ?? 1, Math.min(maxRows ?? rows ?? 1, contentHeight));
|
|
2211
|
-
}, [rows, maxRows, contentHeight]);
|
|
2212
|
-
const cursorLineEnd = cursorLine + 1;
|
|
2213
|
-
const viewportEnd = scrollOffsetRef.current + visibleRows;
|
|
2214
|
-
let newScrollOffset = scrollOffsetRef.current;
|
|
2215
|
-
if (cursorLineEnd <= scrollOffsetRef.current) {
|
|
2216
|
-
newScrollOffset = Math.max(0, cursorLineEnd - 1);
|
|
2217
|
-
} else if (cursorLineEnd > viewportEnd) {
|
|
2218
|
-
newScrollOffset = cursorLineEnd - visibleRows;
|
|
2219
|
-
} else if (contentHeight) {
|
|
2220
|
-
if (contentHeight < visibleRows) {
|
|
2221
|
-
newScrollOffset = 0;
|
|
2222
|
-
} else if (contentHeight < viewportEnd) {
|
|
2223
|
-
newScrollOffset = contentHeight - visibleRows;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
scrollOffsetRef.current = newScrollOffset;
|
|
2227
|
-
const visibleLines = useMemo(() => {
|
|
2228
|
-
return visualLines.slice(newScrollOffset, newScrollOffset + visibleRows);
|
|
2229
|
-
}, [visualLines, newScrollOffset, visibleRows]);
|
|
2230
|
-
const [blink, setBlink] = useState2(true);
|
|
2231
|
-
useEffect2(() => {
|
|
2232
|
-
setBlink(true);
|
|
2233
|
-
if (!focus || !showCursor) return;
|
|
2234
|
-
const timer = setInterval(() => {
|
|
2235
|
-
setBlink((prev) => !prev);
|
|
2236
|
-
}, 530);
|
|
2237
|
-
return () => clearInterval(timer);
|
|
2238
|
-
}, [focus, showCursor, value, cursorIndex]);
|
|
2239
|
-
const cursorStyle = useMemo(() => ({
|
|
2240
|
-
...textStyle,
|
|
2241
|
-
color: showCursor && focus && blink ? "white" : void 0,
|
|
2242
|
-
bold: showCursor && focus && blink,
|
|
2243
|
-
inverse: showCursor && focus && blink
|
|
2244
|
-
}), [textStyle, showCursor, focus, blink]);
|
|
2245
|
-
return /* @__PURE__ */ React2.createElement(Box, { height: visibleRows, width: wrapWidth, overflow: "hidden", flexDirection: "column", flexGrow: 0, flexShrink: 0 }, visibleLines.map((lineObj, idx) => {
|
|
2246
|
-
const globalLineIdx = newScrollOffset + idx;
|
|
2247
|
-
const isCursorLine = globalLineIdx === cursorLine && focus && showCursor;
|
|
2248
|
-
if (!isCursorLine) {
|
|
2249
|
-
return /* @__PURE__ */ React2.createElement(Text2, { key: globalLineIdx, ...textStyle, wrap: "truncate" }, lineObj.text || (placeholder && value.length === 0 ? formatText(placeholder, true) : " "));
|
|
2250
|
-
}
|
|
2251
|
-
const text = lineObj.text;
|
|
2252
|
-
const left = text.slice(0, cursorCol);
|
|
2253
|
-
const charAtCursor = text[cursorCol] || " ";
|
|
2254
|
-
const right = text.slice(cursorCol + 1);
|
|
2255
|
-
return /* @__PURE__ */ React2.createElement(Text2, { key: globalLineIdx, ...textStyle, wrap: "truncate" }, /* @__PURE__ */ React2.createElement(Text2, null, left), /* @__PURE__ */ React2.createElement(Text2, { ...cursorStyle }, charAtCursor), /* @__PURE__ */ React2.createElement(Text2, null, right));
|
|
2256
|
-
}));
|
|
2257
|
-
};
|
|
2258
|
-
MultilineInput = ({
|
|
2259
|
-
value,
|
|
2260
|
-
onChange,
|
|
2261
|
-
onSubmit,
|
|
2262
|
-
keyBindings,
|
|
2263
|
-
showCursor = true,
|
|
2264
|
-
highlightPastedText = false,
|
|
2265
|
-
focus = true,
|
|
2266
|
-
columns = 80,
|
|
2267
|
-
useCustomInput = (inputHandler, isActive) => useInput(inputHandler, { isActive }),
|
|
2268
|
-
...controlledProps
|
|
2269
|
-
}) => {
|
|
2270
|
-
const [cursorIndex, setCursorIndex] = useState2(value.length);
|
|
2271
|
-
const [pasteLength, setPasteLength] = useState2(0);
|
|
2272
|
-
const cursorIndexRef = useRef(value.length);
|
|
2273
|
-
const valueRef = useRef(value);
|
|
2274
|
-
const pasteLengthRef = useRef(0);
|
|
2275
|
-
const lastArrowTimeRef = useRef(0);
|
|
2276
|
-
cursorIndexRef.current = cursorIndex;
|
|
2277
|
-
valueRef.current = value;
|
|
2278
|
-
pasteLengthRef.current = pasteLength;
|
|
2279
|
-
useEffect2(() => {
|
|
2280
|
-
if (cursorIndexRef.current > value.length) {
|
|
2281
|
-
cursorIndexRef.current = value.length;
|
|
2282
|
-
setCursorIndex(value.length);
|
|
2283
|
-
}
|
|
2284
|
-
}, [value]);
|
|
2285
|
-
useCustomInput((input, key) => {
|
|
2286
|
-
if (input === "\x1B[I" || input === "\x1B[O" || input === "[I" || input === "[O") {
|
|
2287
|
-
return;
|
|
2288
|
-
}
|
|
2289
|
-
const isArrowKey = key.upArrow || key.downArrow || key.leftArrow || key.rightArrow;
|
|
2290
|
-
if (isArrowKey) {
|
|
2291
|
-
const now = Date.now();
|
|
2292
|
-
if (now - lastArrowTimeRef.current < 33) {
|
|
2293
|
-
return;
|
|
2294
|
-
}
|
|
2295
|
-
lastArrowTimeRef.current = now;
|
|
2296
|
-
}
|
|
2297
|
-
const curIdx = cursorIndexRef.current;
|
|
2298
|
-
const val = valueRef.current;
|
|
2299
|
-
const wrapWidth = Math.max(20, columns - 10);
|
|
2300
|
-
const submitKey = keyBindings?.submit ?? ((k) => k.return && k.ctrl);
|
|
2301
|
-
const newlineKey = keyBindings?.newline ?? ((k) => k.return);
|
|
2302
|
-
if (submitKey(key)) {
|
|
2303
|
-
onSubmit?.(val);
|
|
2304
|
-
return;
|
|
2305
|
-
} else if (newlineKey(key)) {
|
|
2306
|
-
const newValue = val.slice(0, curIdx) + "\n" + val.slice(curIdx);
|
|
2307
|
-
onChange(newValue);
|
|
2308
|
-
cursorIndexRef.current = curIdx + 1;
|
|
2309
|
-
setCursorIndex(curIdx + 1);
|
|
2310
|
-
setPasteLength(0);
|
|
2311
|
-
return;
|
|
2312
|
-
}
|
|
2313
|
-
if (key.tab || key.shift && key.tab || key.ctrl && input === "c") {
|
|
2314
|
-
return;
|
|
2315
|
-
}
|
|
2316
|
-
const identity = (t) => t;
|
|
2317
|
-
if (key.upArrow || key.downArrow) {
|
|
2318
|
-
if (showCursor) {
|
|
2319
|
-
const { visualLines, cursorLine, cursorCol } = computeVisualMatrix(val, curIdx, wrapWidth, identity);
|
|
2320
|
-
const targetLine = key.upArrow ? cursorLine - 1 : cursorLine + 1;
|
|
2321
|
-
if (targetLine >= 0 && targetLine < visualLines.length) {
|
|
2322
|
-
const targetLineObj = visualLines[targetLine];
|
|
2323
|
-
const targetCol = Math.min(cursorCol, targetLineObj.text.length);
|
|
2324
|
-
const newIndex = targetLineObj.globalStart + targetCol;
|
|
2325
|
-
cursorIndexRef.current = newIndex;
|
|
2326
|
-
setCursorIndex(newIndex);
|
|
2327
|
-
setPasteLength(0);
|
|
2328
|
-
} else if (key.upArrow && cursorLine === 0) {
|
|
2329
|
-
cursorIndexRef.current = 0;
|
|
2330
|
-
setCursorIndex(0);
|
|
2331
|
-
setPasteLength(0);
|
|
2332
|
-
} else if (key.downArrow && cursorLine === visualLines.length - 1) {
|
|
2333
|
-
const lastLineObj = visualLines[visualLines.length - 1];
|
|
2334
|
-
const newIndex = lastLineObj.globalStart + lastLineObj.text.length;
|
|
2335
|
-
cursorIndexRef.current = newIndex;
|
|
2336
|
-
setCursorIndex(newIndex);
|
|
2337
|
-
setPasteLength(0);
|
|
2338
|
-
}
|
|
2339
|
-
}
|
|
2340
|
-
} else if (key.leftArrow) {
|
|
2341
|
-
if (showCursor) {
|
|
2342
|
-
const newIndex = Math.max(0, curIdx - 1);
|
|
2343
|
-
cursorIndexRef.current = newIndex;
|
|
2344
|
-
setCursorIndex(newIndex);
|
|
2345
|
-
setPasteLength(0);
|
|
2346
|
-
}
|
|
2347
|
-
} else if (key.rightArrow) {
|
|
2348
|
-
if (showCursor) {
|
|
2349
|
-
const newIndex = Math.min(val.length, curIdx + 1);
|
|
2350
|
-
cursorIndexRef.current = newIndex;
|
|
2351
|
-
setCursorIndex(newIndex);
|
|
2352
|
-
setPasteLength(0);
|
|
2353
|
-
}
|
|
2354
|
-
} else if (key.backspace) {
|
|
2355
|
-
if (curIdx > 0) {
|
|
2356
|
-
const newValue = val.slice(0, curIdx - 1) + val.slice(curIdx);
|
|
2357
|
-
onChange(newValue);
|
|
2358
|
-
cursorIndexRef.current = curIdx - 1;
|
|
2359
|
-
setCursorIndex(curIdx - 1);
|
|
2360
|
-
setPasteLength(0);
|
|
2361
|
-
}
|
|
2362
|
-
} else if (key.delete) {
|
|
2363
|
-
if (curIdx < val.length) {
|
|
2364
|
-
const newValue = val.slice(0, curIdx) + val.slice(curIdx + 1);
|
|
2365
|
-
onChange(newValue);
|
|
2366
|
-
setPasteLength(0);
|
|
2367
|
-
}
|
|
2368
|
-
} else if (key.home || key.end) {
|
|
2369
|
-
if (showCursor) {
|
|
2370
|
-
const { visualLines, cursorLine } = computeVisualMatrix(val, curIdx, wrapWidth, identity);
|
|
2371
|
-
const currentLineObj = visualLines[cursorLine];
|
|
2372
|
-
if (currentLineObj) {
|
|
2373
|
-
let newIndex;
|
|
2374
|
-
if (key.home) {
|
|
2375
|
-
newIndex = currentLineObj.globalStart;
|
|
2376
|
-
} else if (key.end) {
|
|
2377
|
-
newIndex = currentLineObj.globalStart + currentLineObj.text.length;
|
|
2378
|
-
}
|
|
2379
|
-
cursorIndexRef.current = newIndex;
|
|
2380
|
-
setCursorIndex(newIndex);
|
|
2381
|
-
setPasteLength(0);
|
|
2382
|
-
}
|
|
2383
|
-
}
|
|
2384
|
-
} else {
|
|
2385
|
-
if (input) {
|
|
2386
|
-
const newValue = val.slice(0, curIdx) + input + val.slice(curIdx);
|
|
2387
|
-
onChange(newValue);
|
|
2388
|
-
const newIndex = curIdx + input.length;
|
|
2389
|
-
cursorIndexRef.current = newIndex;
|
|
2390
|
-
setCursorIndex(newIndex);
|
|
2391
|
-
setPasteLength(input.length > 1 ? input.length : 0);
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
|
-
}, focus);
|
|
2395
|
-
return /* @__PURE__ */ React2.createElement(
|
|
2396
|
-
ControlledMultilineInput,
|
|
2397
|
-
{
|
|
2398
|
-
...controlledProps,
|
|
2399
|
-
value,
|
|
2400
|
-
cursorIndex,
|
|
2401
|
-
showCursor,
|
|
2402
|
-
focus,
|
|
2403
|
-
columns
|
|
2404
|
-
}
|
|
2405
|
-
);
|
|
2406
|
-
};
|
|
2407
|
-
}
|
|
2408
|
-
});
|
|
2409
|
-
|
|
2410
2092
|
// src/utils/text.js
|
|
2411
2093
|
import os2 from "os";
|
|
2412
|
-
var wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseMessageToBlocks, TOOL_LABELS, cleanSignals;
|
|
2094
|
+
var wrapText, formatTokens, truncatePath, parsePatchPairs, applyPatches, generateHighFidelityDiff, parseLineInfo, getSimilarity, alignChangeGroup, blocksCache, streamingBlocksCache, MAX_CACHE_SIZE, parseMessageToBlocks, TOOL_LABELS, REGEX_INITIAL_THINK, REGEX_INITIAL_TOOL, REGEX_SYSTEM, REGEX_THINK, REGEX_ANSWER, REGEX_TOOL_RES, REGEX_SUCCESS_ERROR, REGEX_TURN_1, REGEX_END, REGEX_TURN_2, REGEX_TURN_3, REGEX_OPEN_BRACKET, REGEX_RESPONDED, REGEX_PROMPTED, REGEX_ARROWS, REGEX_ARROWS_L, REGEX_ARROWS_U, REGEX_ARROWS_D, REGEX_ARROWS_LR, REGEX_TERMINAL, REGEX_TOOLS, cleanSignals, clearBlocksCache;
|
|
2413
2095
|
var init_text = __esm({
|
|
2414
2096
|
"src/utils/text.js"() {
|
|
2415
2097
|
init_paths();
|
|
@@ -2455,616 +2137,1382 @@ var init_text = __esm({
|
|
|
2455
2137
|
}
|
|
2456
2138
|
}
|
|
2457
2139
|
} else {
|
|
2458
|
-
currentLine += token;
|
|
2459
|
-
currentVisibleLength += tokenVisibleLength;
|
|
2140
|
+
currentLine += token;
|
|
2141
|
+
currentVisibleLength += tokenVisibleLength;
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
if (currentLine.trimEnd().length > 0 || currentLine === indent) {
|
|
2145
|
+
finalLines.push(currentLine.trimEnd());
|
|
2146
|
+
}
|
|
2147
|
+
});
|
|
2148
|
+
return finalLines.join("\n");
|
|
2149
|
+
};
|
|
2150
|
+
formatTokens = (tokens) => {
|
|
2151
|
+
if (!tokens && tokens !== 0) return "0.0k";
|
|
2152
|
+
const num = typeof tokens === "string" ? parseFloat(tokens) : tokens;
|
|
2153
|
+
if (num >= 1e6) {
|
|
2154
|
+
return `${(num / 1e6).toFixed(1)}m`;
|
|
2155
|
+
} else if (num >= 1e3) {
|
|
2156
|
+
return `${(num / 1e3).toFixed(1)}k`;
|
|
2157
|
+
}
|
|
2158
|
+
return num.toString();
|
|
2159
|
+
};
|
|
2160
|
+
truncatePath = (p, maxLength = 40) => {
|
|
2161
|
+
let data_dir = DATA_DIR.replaceAll("\\\\", "\\");
|
|
2162
|
+
p = p.replace(os2.homedir(), "~").replace(data_dir, "FluxFlow").replaceAll("\\", "/");
|
|
2163
|
+
if (!p || p.length <= maxLength) return p;
|
|
2164
|
+
const half = Math.floor((maxLength - 3) / 2);
|
|
2165
|
+
return p.substring(0, half) + "..." + p.substring(p.length - half).replaceAll("\\", "/");
|
|
2166
|
+
};
|
|
2167
|
+
parsePatchPairs = (args) => {
|
|
2168
|
+
const patchPairs = [];
|
|
2169
|
+
const indices = /* @__PURE__ */ new Set();
|
|
2170
|
+
Object.keys(args).forEach((key) => {
|
|
2171
|
+
const m = key.match(/^(replaceContent|newContent|content_to_replace|content_to_add)(\d+)?$/);
|
|
2172
|
+
if (m) {
|
|
2173
|
+
const index = m[2] ? parseInt(m[2]) : 1;
|
|
2174
|
+
indices.add(index);
|
|
2175
|
+
}
|
|
2176
|
+
});
|
|
2177
|
+
const sortedIndices = Array.from(indices).sort((a, b) => a - b);
|
|
2178
|
+
for (const i of sortedIndices) {
|
|
2179
|
+
let r, n;
|
|
2180
|
+
if (i === 1) {
|
|
2181
|
+
r = args.replaceContent1 ?? (args.content_to_replace ?? args.replaceContent);
|
|
2182
|
+
n = args.newContent1 ?? (args.content_to_add ?? args.newContent);
|
|
2183
|
+
} else {
|
|
2184
|
+
r = args[`replaceContent${i}`] ?? args[`content_to_replace${i}`];
|
|
2185
|
+
n = args[`newContent${i}`] ?? args[`content_to_add${i}`];
|
|
2186
|
+
}
|
|
2187
|
+
if (r !== void 0 && n !== void 0) {
|
|
2188
|
+
patchPairs.push({ replace: r, new: n });
|
|
2189
|
+
} else if (r !== void 0 || n !== void 0) {
|
|
2190
|
+
return { error: `Mismatched replacement pair for index ${i}. Both replacement and new content must be provided.` };
|
|
2191
|
+
}
|
|
2192
|
+
}
|
|
2193
|
+
return { patchPairs };
|
|
2194
|
+
};
|
|
2195
|
+
applyPatches = (content, patches) => {
|
|
2196
|
+
let currentFileContent = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2197
|
+
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2198
|
+
const getIndent = (line) => line.match(/^\s*/)[0];
|
|
2199
|
+
const getMinIndent = (text) => {
|
|
2200
|
+
const lines = text.split("\n").filter((l) => l.trim() !== "");
|
|
2201
|
+
if (lines.length === 0) return "";
|
|
2202
|
+
let min = getIndent(lines[0]);
|
|
2203
|
+
for (const line of lines) {
|
|
2204
|
+
const indent = getIndent(line);
|
|
2205
|
+
if (indent.length < min.length) min = indent;
|
|
2206
|
+
}
|
|
2207
|
+
return min;
|
|
2208
|
+
};
|
|
2209
|
+
const adjustIndentation = (newText, originalMatch, leadingContext = "") => {
|
|
2210
|
+
if (!newText || originalMatch === void 0) return newText;
|
|
2211
|
+
const getIndentStyle = (text) => {
|
|
2212
|
+
const lines = text.split("\n").filter((l) => l.trim() !== "");
|
|
2213
|
+
if (lines.length === 0) return { char: " ", size: 4 };
|
|
2214
|
+
const firstIndent = lines[0].match(/^\s*/)[0];
|
|
2215
|
+
if (firstIndent.includes(" ")) return { char: " ", size: 1 };
|
|
2216
|
+
const indents = lines.map((l) => l.match(/^\s*/)[0].length).filter((l) => l > 0);
|
|
2217
|
+
if (indents.length === 0) return { char: " ", size: firstIndent.length || 4 };
|
|
2218
|
+
const gcd = (a, b) => b ? gcd(b, a % b) : a;
|
|
2219
|
+
const step = indents.reduce((a, b) => gcd(a, b));
|
|
2220
|
+
return { char: " ", size: step || 4 };
|
|
2221
|
+
};
|
|
2222
|
+
const fileStyle = getIndentStyle(originalMatch);
|
|
2223
|
+
const modelStyle = getIndentStyle(newText);
|
|
2224
|
+
const matchMinIndent = getMinIndent(originalMatch).length;
|
|
2225
|
+
const leadingIndent = (leadingContext.match(/^\s*/) || [""])[0].length;
|
|
2226
|
+
const targetBaseIndentRaw = leadingIndent + matchMinIndent;
|
|
2227
|
+
const targetUnits = targetBaseIndentRaw / fileStyle.size;
|
|
2228
|
+
const modelBaseUnits = getMinIndent(newText).length / modelStyle.size;
|
|
2229
|
+
const deltaUnits = targetUnits - modelBaseUnits;
|
|
2230
|
+
const newLines = newText.split("\n");
|
|
2231
|
+
return newLines.map((line, i) => {
|
|
2232
|
+
if (line.trim() === "" && i !== 0) return "";
|
|
2233
|
+
const currentLineUnits = line.match(/^\s*/)[0].length / modelStyle.size;
|
|
2234
|
+
const finalUnits = Math.max(0, currentLineUnits + deltaUnits);
|
|
2235
|
+
let unitCount = finalUnits;
|
|
2236
|
+
if (i === 0) {
|
|
2237
|
+
const leadingUnits = leadingIndent / fileStyle.size;
|
|
2238
|
+
unitCount = Math.max(0, finalUnits - leadingUnits);
|
|
2239
|
+
}
|
|
2240
|
+
return fileStyle.char.repeat(unitCount * fileStyle.size) + line.trimStart();
|
|
2241
|
+
}).join("\n");
|
|
2242
|
+
};
|
|
2243
|
+
const patchMatches = [];
|
|
2244
|
+
for (let i = 0; i < patches.length; i++) {
|
|
2245
|
+
const pair = patches[i];
|
|
2246
|
+
const content_to_replace = strip(pair.replace || "");
|
|
2247
|
+
const content_to_add = strip(pair.new || "");
|
|
2248
|
+
if (content_to_replace === "" && content_to_add === "") {
|
|
2249
|
+
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Empty replace and add content.` });
|
|
2250
|
+
continue;
|
|
2251
|
+
}
|
|
2252
|
+
const exactPattern = content_to_replace.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2253
|
+
let matchRegex = null;
|
|
2254
|
+
if (content_to_replace !== "" && currentFileContent.includes(content_to_replace)) {
|
|
2255
|
+
matchRegex = new RegExp(exactPattern, "g");
|
|
2256
|
+
} else {
|
|
2257
|
+
const fuzzyLines = content_to_replace.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line) => line.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\s+/g, "\\s*"));
|
|
2258
|
+
if (fuzzyLines.length > 0) {
|
|
2259
|
+
const fuzzyPattern = fuzzyLines.join("\\s*");
|
|
2260
|
+
try {
|
|
2261
|
+
matchRegex = new RegExp(fuzzyPattern, "g");
|
|
2262
|
+
} catch (e) {
|
|
2263
|
+
matchRegex = new RegExp(exactPattern, "g");
|
|
2264
|
+
}
|
|
2265
|
+
} else {
|
|
2266
|
+
matchRegex = new RegExp(exactPattern, "g");
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
const matches = [...currentFileContent.matchAll(matchRegex)];
|
|
2270
|
+
if (matches.length === 0) {
|
|
2271
|
+
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Could not find match.` });
|
|
2272
|
+
continue;
|
|
2273
|
+
}
|
|
2274
|
+
if (matches.length > 1) {
|
|
2275
|
+
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique).` });
|
|
2276
|
+
continue;
|
|
2277
|
+
}
|
|
2278
|
+
patchMatches.push({
|
|
2279
|
+
index: i,
|
|
2280
|
+
success: true,
|
|
2281
|
+
startPos: matches[0].index,
|
|
2282
|
+
firstMatchContent: matches[0][0],
|
|
2283
|
+
content_to_add
|
|
2284
|
+
});
|
|
2285
|
+
}
|
|
2286
|
+
const successful = patchMatches.filter((m) => m.success).sort((a, b) => a.startPos - b.startPos);
|
|
2287
|
+
for (let j = 0; j < successful.length - 1; j++) {
|
|
2288
|
+
const curr = successful[j];
|
|
2289
|
+
const next = successful[j + 1];
|
|
2290
|
+
if (curr.startPos + curr.firstMatchContent.length > next.startPos) {
|
|
2291
|
+
curr.success = false;
|
|
2292
|
+
curr.error = `Block ${curr.index + 1}: Overlaps with another block.`;
|
|
2293
|
+
next.success = false;
|
|
2294
|
+
next.error = `Block ${next.index + 1}: Overlaps with another block.`;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
const resultsMap = /* @__PURE__ */ new Map();
|
|
2298
|
+
let finalContent = currentFileContent;
|
|
2299
|
+
let charOffset = 0;
|
|
2300
|
+
let lineOffset = 0;
|
|
2301
|
+
const toApply = patchMatches.filter((m) => m.success).sort((a, b) => a.startPos - b.startPos);
|
|
2302
|
+
for (const match of toApply) {
|
|
2303
|
+
const originalStartPos = match.startPos;
|
|
2304
|
+
const originalStartLine = currentFileContent.substring(0, originalStartPos).split("\n").length;
|
|
2305
|
+
const finalStartPos = originalStartPos + charOffset;
|
|
2306
|
+
const finalStartLine = originalStartLine + lineOffset;
|
|
2307
|
+
const lineStart = finalContent.lastIndexOf("\n", finalStartPos) + 1;
|
|
2308
|
+
const leadingContext = finalContent.substring(lineStart, finalStartPos);
|
|
2309
|
+
const finalReplacement = adjustIndentation(match.content_to_add, match.firstMatchContent, leadingContext);
|
|
2310
|
+
const allLines = finalContent.split("\n");
|
|
2311
|
+
const contextBefore = [];
|
|
2312
|
+
for (let j = Math.max(0, finalStartLine - 4); j < finalStartLine - 1; j++) {
|
|
2313
|
+
contextBefore.push({ num: j + 1, text: allLines[j] });
|
|
2314
|
+
}
|
|
2315
|
+
const patchOldLines = match.firstMatchContent.split("\n");
|
|
2316
|
+
const contextAfter = [];
|
|
2317
|
+
const patchEndLineIdx = finalStartLine + patchOldLines.length - 1;
|
|
2318
|
+
for (let j = patchEndLineIdx; j < Math.min(allLines.length, patchEndLineIdx + 3); j++) {
|
|
2319
|
+
contextAfter.push({ num: j + 1, text: allLines[j] });
|
|
2320
|
+
}
|
|
2321
|
+
resultsMap.set(match.index, {
|
|
2322
|
+
success: true,
|
|
2323
|
+
oldContent: match.firstMatchContent,
|
|
2324
|
+
newContent: finalReplacement,
|
|
2325
|
+
originalStartLine,
|
|
2326
|
+
finalStartLine,
|
|
2327
|
+
contextBefore,
|
|
2328
|
+
contextAfter
|
|
2329
|
+
});
|
|
2330
|
+
finalContent = finalContent.substring(0, finalStartPos) + finalReplacement + finalContent.substring(finalStartPos + match.firstMatchContent.length);
|
|
2331
|
+
charOffset += finalReplacement.length - match.firstMatchContent.length;
|
|
2332
|
+
lineOffset += finalReplacement.split("\n").length - match.firstMatchContent.split("\n").length;
|
|
2333
|
+
}
|
|
2334
|
+
const results = [];
|
|
2335
|
+
for (let i = 0; i < patches.length; i++) {
|
|
2336
|
+
if (resultsMap.has(i)) {
|
|
2337
|
+
results.push(resultsMap.get(i));
|
|
2338
|
+
} else {
|
|
2339
|
+
const match = patchMatches.find((m) => m.index === i);
|
|
2340
|
+
results.push({
|
|
2341
|
+
success: false,
|
|
2342
|
+
error: match ? match.error : `Block ${i + 1}: Unknown error.`
|
|
2343
|
+
});
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
return { content: finalContent, results };
|
|
2347
|
+
};
|
|
2348
|
+
generateHighFidelityDiff = (originalContent, finalContent, patchResults, threshold = 8) => {
|
|
2349
|
+
if (!patchResults || patchResults.length === 0) return "";
|
|
2350
|
+
const allLinesOriginal = originalContent.split(/\r?\n/);
|
|
2351
|
+
const allLinesFinal = finalContent.split(/\r?\n/);
|
|
2352
|
+
let diffText = `[DIFF_START]
|
|
2353
|
+
`;
|
|
2354
|
+
const separatorLine = "\u2550".repeat(88);
|
|
2355
|
+
let currentFinalLineIdx = 0;
|
|
2356
|
+
let lastSuccessfulHunk = null;
|
|
2357
|
+
const sortedResults = patchResults.filter((res) => res.success).sort((a, b) => a.originalStartLine - b.originalStartLine);
|
|
2358
|
+
sortedResults.forEach((res, idx) => {
|
|
2359
|
+
const startLineFinal = res.finalStartLine !== void 0 ? res.finalStartLine : res.originalStartLine;
|
|
2360
|
+
if (lastSuccessfulHunk === null) {
|
|
2361
|
+
const contextStart = Math.max(0, startLineFinal - 4);
|
|
2362
|
+
currentFinalLineIdx = contextStart;
|
|
2363
|
+
while (currentFinalLineIdx < startLineFinal - 1) {
|
|
2364
|
+
diffText += `[UI_CONTEXT] ${currentFinalLineIdx + 1} |${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2365
|
+
`;
|
|
2366
|
+
currentFinalLineIdx++;
|
|
2367
|
+
}
|
|
2368
|
+
} else {
|
|
2369
|
+
const prev = lastSuccessfulHunk;
|
|
2370
|
+
const prevOriginalEnd = prev.originalStartLine + prev.oldContent.split("\n").length - 1;
|
|
2371
|
+
const gap = res.originalStartLine - prevOriginalEnd - 1;
|
|
2372
|
+
if (gap >= threshold) {
|
|
2373
|
+
let afterLimit = Math.min(allLinesFinal.length, currentFinalLineIdx + 3);
|
|
2374
|
+
while (currentFinalLineIdx < afterLimit) {
|
|
2375
|
+
diffText += `[UI_CONTEXT] ${currentFinalLineIdx + 1} |${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2376
|
+
`;
|
|
2377
|
+
currentFinalLineIdx++;
|
|
2378
|
+
}
|
|
2379
|
+
diffText += `[UI_CONTEXT] ${separatorLine}
|
|
2380
|
+
`;
|
|
2381
|
+
const beforeStart = Math.max(currentFinalLineIdx, startLineFinal - 4);
|
|
2382
|
+
currentFinalLineIdx = beforeStart;
|
|
2383
|
+
while (currentFinalLineIdx < startLineFinal - 1) {
|
|
2384
|
+
diffText += `[UI_CONTEXT] ${currentFinalLineIdx + 1} |${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2385
|
+
`;
|
|
2386
|
+
currentFinalLineIdx++;
|
|
2387
|
+
}
|
|
2388
|
+
} else {
|
|
2389
|
+
while (currentFinalLineIdx < startLineFinal - 1) {
|
|
2390
|
+
diffText += `[UI_CONTEXT] ${currentFinalLineIdx + 1} |${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2391
|
+
`;
|
|
2392
|
+
currentFinalLineIdx++;
|
|
2393
|
+
}
|
|
2460
2394
|
}
|
|
2395
|
+
}
|
|
2396
|
+
const oldLines = res.oldContent.split("\n");
|
|
2397
|
+
oldLines.forEach((line, i) => {
|
|
2398
|
+
diffText += `-${res.originalStartLine + i}|${line}
|
|
2399
|
+
`;
|
|
2461
2400
|
});
|
|
2462
|
-
|
|
2463
|
-
|
|
2401
|
+
let hunkEndInFinal = currentFinalLineIdx;
|
|
2402
|
+
if (res.finalStartLine !== void 0) {
|
|
2403
|
+
hunkEndInFinal = res.finalStartLine - 1 + (res.newContent ? res.newContent.split("\n").length : 0);
|
|
2404
|
+
} else {
|
|
2405
|
+
const originalResyncLineIdx = res.originalStartLine + oldLines.length - 1;
|
|
2406
|
+
const resyncAnchorText = allLinesOriginal[originalResyncLineIdx] || null;
|
|
2407
|
+
if (resyncAnchorText !== null) {
|
|
2408
|
+
const lookAheadLimit = idx < sortedResults.length - 1 ? (sortedResults[idx + 1].originalStartLine || allLinesFinal.length) + 10 : allLinesFinal.length;
|
|
2409
|
+
for (let s = currentFinalLineIdx; s < lookAheadLimit; s++) {
|
|
2410
|
+
if (allLinesFinal[s] === resyncAnchorText) {
|
|
2411
|
+
hunkEndInFinal = s;
|
|
2412
|
+
break;
|
|
2413
|
+
}
|
|
2414
|
+
if (s === allLinesFinal.length - 1) hunkEndInFinal = allLinesFinal.length;
|
|
2415
|
+
}
|
|
2416
|
+
} else {
|
|
2417
|
+
hunkEndInFinal = allLinesFinal.length;
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
while (currentFinalLineIdx < hunkEndInFinal) {
|
|
2421
|
+
diffText += `+${currentFinalLineIdx + 1}|${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2422
|
+
`;
|
|
2423
|
+
currentFinalLineIdx++;
|
|
2464
2424
|
}
|
|
2425
|
+
lastSuccessfulHunk = res;
|
|
2465
2426
|
});
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
} else if (num >= 1e3) {
|
|
2474
|
-
return `${(num / 1e3).toFixed(1)}k`;
|
|
2427
|
+
if (lastSuccessfulHunk !== null) {
|
|
2428
|
+
let limit = Math.min(allLinesFinal.length, currentFinalLineIdx + 3);
|
|
2429
|
+
while (currentFinalLineIdx < limit) {
|
|
2430
|
+
diffText += `[UI_CONTEXT] ${currentFinalLineIdx + 1} |${allLinesFinal[currentFinalLineIdx] || ""}
|
|
2431
|
+
`;
|
|
2432
|
+
currentFinalLineIdx++;
|
|
2433
|
+
}
|
|
2475
2434
|
}
|
|
2476
|
-
|
|
2435
|
+
diffText += `[DIFF_END]`;
|
|
2436
|
+
return diffText;
|
|
2477
2437
|
};
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
const
|
|
2483
|
-
|
|
2438
|
+
parseLineInfo = (l) => {
|
|
2439
|
+
if (!l) return null;
|
|
2440
|
+
const clean = l.replace("[UI_CONTEXT]", "").replace(/\r/g, "");
|
|
2441
|
+
const isR = clean.startsWith("-");
|
|
2442
|
+
const isA = clean.startsWith("+");
|
|
2443
|
+
let rest = isR || isA ? clean.substring(1) : clean;
|
|
2444
|
+
rest = rest.trim();
|
|
2445
|
+
const splitIdx = rest.indexOf("|");
|
|
2446
|
+
const num = splitIdx !== -1 ? rest.substring(0, splitIdx).trim() : "";
|
|
2447
|
+
const content = splitIdx !== -1 ? rest.substring(splitIdx + 1) : rest;
|
|
2448
|
+
return { isR, isA, num, content };
|
|
2484
2449
|
};
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2450
|
+
getSimilarity = (s1, s2) => {
|
|
2451
|
+
if (!s1 && !s2) return 1;
|
|
2452
|
+
if (!s1 || !s2) return 0;
|
|
2453
|
+
const l1 = s1.length;
|
|
2454
|
+
const l2 = s2.length;
|
|
2455
|
+
const dp = Array.from({ length: l1 + 1 }, () => Array(l2 + 1).fill(0));
|
|
2456
|
+
for (let i = 0; i <= l1; i++) dp[i][0] = i;
|
|
2457
|
+
for (let j = 0; j <= l2; j++) dp[0][j] = j;
|
|
2458
|
+
for (let i = 1; i <= l1; i++) {
|
|
2459
|
+
for (let j = 1; j <= l2; j++) {
|
|
2460
|
+
if (s1[i - 1] === s2[j - 1]) {
|
|
2461
|
+
dp[i][j] = dp[i - 1][j - 1];
|
|
2462
|
+
} else {
|
|
2463
|
+
dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
const maxLen = Math.max(l1, l2);
|
|
2468
|
+
if (maxLen === 0) return 1;
|
|
2469
|
+
return 1 - dp[l1][l2] / maxLen;
|
|
2470
|
+
};
|
|
2471
|
+
alignChangeGroup = (group) => {
|
|
2472
|
+
const removals = [];
|
|
2473
|
+
const additions = [];
|
|
2474
|
+
group.forEach((item, index) => {
|
|
2475
|
+
if (item.parsed.isR) {
|
|
2476
|
+
removals.push({ index, content: item.parsed.content });
|
|
2477
|
+
} else if (item.parsed.isA) {
|
|
2478
|
+
additions.push({ index, content: item.parsed.content });
|
|
2493
2479
|
}
|
|
2494
2480
|
});
|
|
2495
|
-
const
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2481
|
+
const N = removals.length;
|
|
2482
|
+
const M = additions.length;
|
|
2483
|
+
if (N === 0 || M === 0) return;
|
|
2484
|
+
const dp = Array.from({ length: N + 1 }, () => Array(M + 1).fill(0));
|
|
2485
|
+
const choices = Array.from({ length: N + 1 }, () => Array(M + 1).fill(""));
|
|
2486
|
+
for (let i2 = 1; i2 <= N; i2++) choices[i2][0] = "up";
|
|
2487
|
+
for (let j2 = 1; j2 <= M; j2++) choices[0][j2] = "left";
|
|
2488
|
+
const simMatrix = Array.from({ length: N }, () => Array(M).fill(0));
|
|
2489
|
+
for (let i2 = 0; i2 < N; i2++) {
|
|
2490
|
+
for (let j2 = 0; j2 < M; j2++) {
|
|
2491
|
+
simMatrix[i2][j2] = getSimilarity(removals[i2].content.trim(), additions[j2].content.trim());
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
for (let i2 = 1; i2 <= N; i2++) {
|
|
2495
|
+
for (let j2 = 1; j2 <= M; j2++) {
|
|
2496
|
+
const matchScore = simMatrix[i2 - 1][j2 - 1];
|
|
2497
|
+
const score = matchScore >= 0.2 ? matchScore : -10;
|
|
2498
|
+
const diag = dp[i2 - 1][j2 - 1] + score;
|
|
2499
|
+
const up = dp[i2 - 1][j2];
|
|
2500
|
+
const left = dp[i2][j2 - 1];
|
|
2501
|
+
if (diag >= up && diag >= left) {
|
|
2502
|
+
dp[i2][j2] = diag;
|
|
2503
|
+
choices[i2][j2] = "diag";
|
|
2504
|
+
} else if (up >= left) {
|
|
2505
|
+
dp[i2][j2] = up;
|
|
2506
|
+
choices[i2][j2] = "up";
|
|
2507
|
+
} else {
|
|
2508
|
+
dp[i2][j2] = left;
|
|
2509
|
+
choices[i2][j2] = "left";
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
let i = N;
|
|
2514
|
+
let j = M;
|
|
2515
|
+
while (i > 0 || j > 0) {
|
|
2516
|
+
if (choices[i][j] === "diag") {
|
|
2517
|
+
const matchScore = simMatrix[i - 1][j - 1];
|
|
2518
|
+
if (matchScore >= 0.2) {
|
|
2519
|
+
const rIdx = removals[i - 1].index;
|
|
2520
|
+
const aIdx = additions[j - 1].index;
|
|
2521
|
+
group[rIdx].pairContent = group[aIdx].parsed.content;
|
|
2522
|
+
group[aIdx].pairContent = group[rIdx].parsed.content;
|
|
2523
|
+
}
|
|
2524
|
+
i--;
|
|
2525
|
+
j--;
|
|
2526
|
+
} else if (choices[i][j] === "up") {
|
|
2527
|
+
i--;
|
|
2501
2528
|
} else {
|
|
2502
|
-
|
|
2503
|
-
n = args[`newContent${i}`] ?? args[`content_to_add${i}`];
|
|
2504
|
-
}
|
|
2505
|
-
if (r !== void 0 && n !== void 0) {
|
|
2506
|
-
patchPairs.push({ replace: r, new: n });
|
|
2507
|
-
} else if (r !== void 0 || n !== void 0) {
|
|
2508
|
-
return { error: `Mismatched replacement pair for index ${i}. Both replacement and new content must be provided.` };
|
|
2529
|
+
j--;
|
|
2509
2530
|
}
|
|
2510
2531
|
}
|
|
2511
|
-
return { patchPairs };
|
|
2512
2532
|
};
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2533
|
+
blocksCache = /* @__PURE__ */ new Map();
|
|
2534
|
+
streamingBlocksCache = /* @__PURE__ */ new Map();
|
|
2535
|
+
MAX_CACHE_SIZE = 200;
|
|
2536
|
+
parseMessageToBlocks = (msg, columns) => {
|
|
2537
|
+
if (!msg) return { completed: [], active: [] };
|
|
2538
|
+
const cacheKey = `${msg.id}-${msg.text?.length || 0}-${columns}-${msg.isStreaming}`;
|
|
2539
|
+
if (!msg.isStreaming && blocksCache.has(cacheKey)) {
|
|
2540
|
+
return blocksCache.get(cacheKey);
|
|
2541
|
+
}
|
|
2542
|
+
const text = cleanSignals(msg.text || "");
|
|
2543
|
+
const streamCacheKey = `${msg.id}-${columns}`;
|
|
2544
|
+
let cachedBlocks = /* @__PURE__ */ new Map();
|
|
2545
|
+
if (msg.isStreaming) {
|
|
2546
|
+
const cached = streamingBlocksCache.get(streamCacheKey);
|
|
2547
|
+
if (cached && text.startsWith(cached.text)) {
|
|
2548
|
+
cachedBlocks = cached.blocksMap;
|
|
2524
2549
|
}
|
|
2525
|
-
|
|
2550
|
+
}
|
|
2551
|
+
const getBlock = (key, type, textContent, extra = {}) => {
|
|
2552
|
+
const existing = cachedBlocks.get(key);
|
|
2553
|
+
if (existing && existing.text === textContent && existing.type === type && !!existing.isActiveBlock === !!extra.isActiveBlock && !!existing.isStreaming === !!extra.isStreaming && existing.pairContent === extra.pairContent) {
|
|
2554
|
+
return existing;
|
|
2555
|
+
}
|
|
2556
|
+
return {
|
|
2557
|
+
key,
|
|
2558
|
+
msg,
|
|
2559
|
+
type,
|
|
2560
|
+
text: textContent,
|
|
2561
|
+
...extra
|
|
2562
|
+
};
|
|
2526
2563
|
};
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
const
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2564
|
+
if (text.includes("- Content Preview:")) {
|
|
2565
|
+
const mainParts = text.split("- Content Preview:");
|
|
2566
|
+
const headerText = mainParts[0] || "";
|
|
2567
|
+
const contentPart = mainParts[1] || "";
|
|
2568
|
+
const footerMarker = "[SYSTEM] Check the content preview for verification [/SYSTEM]";
|
|
2569
|
+
const contentAndFooter = contentPart.split(footerMarker);
|
|
2570
|
+
const content = contentAndFooter[0]?.trim() || "";
|
|
2571
|
+
const footer = contentAndFooter[1] ? `${footerMarker}${contentAndFooter[1]}` : "";
|
|
2572
|
+
const codeLines = content.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
2573
|
+
const gutterWidth = String(codeLines.length).length;
|
|
2574
|
+
const completedBlocks2 = [];
|
|
2575
|
+
let activeBlock2 = null;
|
|
2576
|
+
codeLines.forEach((line, idx) => {
|
|
2577
|
+
const isLast = idx === codeLines.length - 1;
|
|
2578
|
+
const block = getBlock(`${msg.id || Date.now()}-write-line-${idx}`, "write-line", line, {
|
|
2579
|
+
gutterWidth,
|
|
2580
|
+
lineNum: idx + 1,
|
|
2581
|
+
isFirstLine: idx === 0,
|
|
2582
|
+
isLastLine: isLast
|
|
2583
|
+
});
|
|
2584
|
+
if (isLast && msg.isStreaming) {
|
|
2585
|
+
activeBlock2 = block;
|
|
2586
|
+
} else {
|
|
2587
|
+
completedBlocks2.push(block);
|
|
2588
|
+
}
|
|
2589
|
+
});
|
|
2590
|
+
return {
|
|
2591
|
+
completed: completedBlocks2,
|
|
2592
|
+
active: activeBlock2 ? [activeBlock2] : []
|
|
2539
2593
|
};
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
const
|
|
2543
|
-
const
|
|
2544
|
-
const
|
|
2545
|
-
const
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2594
|
+
}
|
|
2595
|
+
if (text.includes("[DIFF_START]")) {
|
|
2596
|
+
const match = text.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
|
|
2597
|
+
const diffBody = match ? match[1].trim() : "";
|
|
2598
|
+
const diffLines = diffBody.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
2599
|
+
const parsedLines = diffLines.map((line) => {
|
|
2600
|
+
return {
|
|
2601
|
+
line,
|
|
2602
|
+
parsed: parseLineInfo(line),
|
|
2603
|
+
pairContent: null
|
|
2604
|
+
};
|
|
2605
|
+
});
|
|
2606
|
+
let currentGroup = [];
|
|
2607
|
+
for (let i = 0; i < parsedLines.length; i++) {
|
|
2608
|
+
const item = parsedLines[i];
|
|
2609
|
+
if (item.parsed && (item.parsed.isR || item.parsed.isA)) {
|
|
2610
|
+
currentGroup.push(item);
|
|
2611
|
+
} else {
|
|
2612
|
+
if (currentGroup.length > 0) {
|
|
2613
|
+
alignChangeGroup(currentGroup);
|
|
2614
|
+
currentGroup = [];
|
|
2615
|
+
}
|
|
2557
2616
|
}
|
|
2558
|
-
return fileStyle.char.repeat(unitCount * fileStyle.size) + line.trimStart();
|
|
2559
|
-
}).join("\n");
|
|
2560
|
-
};
|
|
2561
|
-
const patchMatches = [];
|
|
2562
|
-
for (let i = 0; i < patches.length; i++) {
|
|
2563
|
-
const pair = patches[i];
|
|
2564
|
-
const content_to_replace = strip(pair.replace || "");
|
|
2565
|
-
const content_to_add = strip(pair.new || "");
|
|
2566
|
-
if (content_to_replace === "" && content_to_add === "") {
|
|
2567
|
-
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Empty replace and add content.` });
|
|
2568
|
-
continue;
|
|
2569
2617
|
}
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2618
|
+
if (currentGroup.length > 0) {
|
|
2619
|
+
alignChangeGroup(currentGroup);
|
|
2620
|
+
}
|
|
2621
|
+
const completedBlocks2 = [];
|
|
2622
|
+
let activeBlock2 = null;
|
|
2623
|
+
diffLines.forEach((line, i) => {
|
|
2624
|
+
const isLast = i === diffLines.length - 1;
|
|
2625
|
+
const block = getBlock(`${msg.id || Date.now()}-diff-${i}`, "diff-line", line, {
|
|
2626
|
+
isFirstLine: i === 0,
|
|
2627
|
+
isLastLine: isLast,
|
|
2628
|
+
pairContent: parsedLines[i].pairContent
|
|
2629
|
+
});
|
|
2630
|
+
if (isLast && msg.isStreaming) {
|
|
2631
|
+
activeBlock2 = block;
|
|
2632
|
+
} else {
|
|
2633
|
+
completedBlocks2.push(block);
|
|
2634
|
+
}
|
|
2635
|
+
});
|
|
2636
|
+
return {
|
|
2637
|
+
completed: completedBlocks2,
|
|
2638
|
+
active: activeBlock2 ? [activeBlock2] : []
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2641
|
+
if (msg.role === "system" || msg.isLogo || msg.isHelpRecord || msg.isTerminalRecord || msg.isHomeWarning || msg.isImageStats || msg.isAskRecord || msg.isAboutRecord || msg.isUpdateNotification || msg.role === "user") {
|
|
2642
|
+
return {
|
|
2643
|
+
completed: [getBlock(`${msg.id || Date.now()}-full`, "full-message", text)],
|
|
2644
|
+
active: []
|
|
2645
|
+
};
|
|
2646
|
+
}
|
|
2647
|
+
const completedBlocks = [];
|
|
2648
|
+
let activeBlock = null;
|
|
2649
|
+
if (msg.role === "think") {
|
|
2650
|
+
completedBlocks.push(getBlock(`${msg.id}-header`, "think-header", ""));
|
|
2651
|
+
const lines = text.split("\n");
|
|
2652
|
+
lines.forEach((line, idx) => {
|
|
2653
|
+
const isLast = idx === lines.length - 1;
|
|
2654
|
+
const block = getBlock(`${msg.id}-${idx}`, "think-line", line, isLast && msg.isStreaming ? { isActiveBlock: true } : {});
|
|
2655
|
+
if (isLast && msg.isStreaming) {
|
|
2656
|
+
activeBlock = block;
|
|
2657
|
+
} else {
|
|
2658
|
+
completedBlocks.push(block);
|
|
2659
|
+
}
|
|
2660
|
+
});
|
|
2661
|
+
if (!msg.isStreaming) {
|
|
2662
|
+
completedBlocks.push({
|
|
2663
|
+
key: `${msg.id}-footer-padding`,
|
|
2664
|
+
msg,
|
|
2665
|
+
type: "think-footer-padding",
|
|
2666
|
+
text: ""
|
|
2667
|
+
});
|
|
2668
|
+
}
|
|
2669
|
+
} else {
|
|
2670
|
+
const lines = text.split("\n");
|
|
2671
|
+
let inTable = false;
|
|
2672
|
+
let tableLines = [];
|
|
2673
|
+
let inCodeBlock = false;
|
|
2674
|
+
let codeLines = [];
|
|
2675
|
+
lines.forEach((line, idx) => {
|
|
2676
|
+
const isLast = idx === lines.length - 1;
|
|
2677
|
+
const isTableRow = line.trim().startsWith("|");
|
|
2678
|
+
const isCodeBlockMarker = line.trim().startsWith("```");
|
|
2679
|
+
if (inCodeBlock) {
|
|
2680
|
+
codeLines.push(line);
|
|
2681
|
+
if (isCodeBlockMarker || isLast) {
|
|
2682
|
+
inCodeBlock = !isCodeBlockMarker;
|
|
2683
|
+
if (!inCodeBlock || isLast) {
|
|
2684
|
+
const block = getBlock(`${msg.id}-code-${idx}`, "agent-line", codeLines.join("\n"), isLast && msg.isStreaming && inCodeBlock ? { isActiveBlock: true } : {});
|
|
2685
|
+
if (isLast && msg.isStreaming && inCodeBlock) {
|
|
2686
|
+
activeBlock = block;
|
|
2687
|
+
} else {
|
|
2688
|
+
completedBlocks.push(block);
|
|
2689
|
+
}
|
|
2690
|
+
codeLines = [];
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
} else if (isCodeBlockMarker) {
|
|
2694
|
+
inCodeBlock = true;
|
|
2695
|
+
codeLines.push(line);
|
|
2696
|
+
if (isLast) {
|
|
2697
|
+
const block = getBlock(`${msg.id}-code-${idx}`, "agent-line", codeLines.join("\n"), msg.isStreaming ? { isActiveBlock: true } : {});
|
|
2698
|
+
if (msg.isStreaming) {
|
|
2699
|
+
activeBlock = block;
|
|
2700
|
+
} else {
|
|
2701
|
+
completedBlocks.push(block);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
} else if (isTableRow) {
|
|
2705
|
+
inTable = true;
|
|
2706
|
+
tableLines.push(line);
|
|
2707
|
+
if (isLast) {
|
|
2708
|
+
if (msg.isStreaming) {
|
|
2709
|
+
activeBlock = getBlock(`${msg.id}-table-${idx}`, "table", tableLines.join("\n"), { isStreaming: true, isActiveBlock: true });
|
|
2710
|
+
} else {
|
|
2711
|
+
completedBlocks.push(getBlock(`${msg.id}-table-${idx}`, "table", tableLines.join("\n"), { isStreaming: false }));
|
|
2712
|
+
}
|
|
2582
2713
|
}
|
|
2583
2714
|
} else {
|
|
2584
|
-
|
|
2715
|
+
if (inTable) {
|
|
2716
|
+
completedBlocks.push(getBlock(`${msg.id}-table-${idx}`, "table", tableLines.join("\n"), { isStreaming: false }));
|
|
2717
|
+
inTable = false;
|
|
2718
|
+
tableLines = [];
|
|
2719
|
+
}
|
|
2720
|
+
const block = getBlock(`${msg.id}-${idx}`, "agent-line", line, isLast && msg.isStreaming ? { isActiveBlock: true } : {});
|
|
2721
|
+
if (isLast && msg.isStreaming) {
|
|
2722
|
+
activeBlock = block;
|
|
2723
|
+
} else {
|
|
2724
|
+
completedBlocks.push(block);
|
|
2725
|
+
}
|
|
2585
2726
|
}
|
|
2586
|
-
}
|
|
2587
|
-
const matches = [...currentFileContent.matchAll(matchRegex)];
|
|
2588
|
-
if (matches.length === 0) {
|
|
2589
|
-
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Could not find match.` });
|
|
2590
|
-
continue;
|
|
2591
|
-
}
|
|
2592
|
-
if (matches.length > 1) {
|
|
2593
|
-
patchMatches.push({ index: i, success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique).` });
|
|
2594
|
-
continue;
|
|
2595
|
-
}
|
|
2596
|
-
patchMatches.push({
|
|
2597
|
-
index: i,
|
|
2598
|
-
success: true,
|
|
2599
|
-
startPos: matches[0].index,
|
|
2600
|
-
firstMatchContent: matches[0][0],
|
|
2601
|
-
content_to_add
|
|
2602
2727
|
});
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
for (let j = 0; j < successful.length - 1; j++) {
|
|
2606
|
-
const curr = successful[j];
|
|
2607
|
-
const next = successful[j + 1];
|
|
2608
|
-
if (curr.startPos + curr.firstMatchContent.length > next.startPos) {
|
|
2609
|
-
curr.success = false;
|
|
2610
|
-
curr.error = `Block ${curr.index + 1}: Overlaps with another block.`;
|
|
2611
|
-
next.success = false;
|
|
2612
|
-
next.error = `Block ${next.index + 1}: Overlaps with another block.`;
|
|
2728
|
+
if (!msg.isStreaming && msg.workedDuration) {
|
|
2729
|
+
completedBlocks.push(getBlock(`${msg.id}-worked-duration`, "worked-duration", ""));
|
|
2613
2730
|
}
|
|
2614
2731
|
}
|
|
2615
|
-
const
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
const finalStartLine = originalStartLine + lineOffset;
|
|
2625
|
-
const lineStart = finalContent.lastIndexOf("\n", finalStartPos) + 1;
|
|
2626
|
-
const leadingContext = finalContent.substring(lineStart, finalStartPos);
|
|
2627
|
-
const finalReplacement = adjustIndentation(match.content_to_add, match.firstMatchContent, leadingContext);
|
|
2628
|
-
const allLines = finalContent.split("\n");
|
|
2629
|
-
const contextBefore = [];
|
|
2630
|
-
for (let j = Math.max(0, finalStartLine - 4); j < finalStartLine - 1; j++) {
|
|
2631
|
-
contextBefore.push({ num: j + 1, text: allLines[j] });
|
|
2632
|
-
}
|
|
2633
|
-
const patchOldLines = match.firstMatchContent.split("\n");
|
|
2634
|
-
const contextAfter = [];
|
|
2635
|
-
const patchEndLineIdx = finalStartLine + patchOldLines.length - 1;
|
|
2636
|
-
for (let j = patchEndLineIdx; j < Math.min(allLines.length, patchEndLineIdx + 3); j++) {
|
|
2637
|
-
contextAfter.push({ num: j + 1, text: allLines[j] });
|
|
2732
|
+
const result = {
|
|
2733
|
+
completed: completedBlocks,
|
|
2734
|
+
active: activeBlock ? [activeBlock] : []
|
|
2735
|
+
};
|
|
2736
|
+
if (!msg.isStreaming) {
|
|
2737
|
+
blocksCache.set(cacheKey, result);
|
|
2738
|
+
if (blocksCache.size > MAX_CACHE_SIZE) {
|
|
2739
|
+
const firstKey = blocksCache.keys().next().value;
|
|
2740
|
+
blocksCache.delete(firstKey);
|
|
2638
2741
|
}
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2742
|
+
streamingBlocksCache.delete(streamCacheKey);
|
|
2743
|
+
} else {
|
|
2744
|
+
const blocksMap = /* @__PURE__ */ new Map();
|
|
2745
|
+
completedBlocks.forEach((b) => blocksMap.set(b.key, b));
|
|
2746
|
+
if (activeBlock) {
|
|
2747
|
+
blocksMap.set(activeBlock.key, activeBlock);
|
|
2748
|
+
}
|
|
2749
|
+
streamingBlocksCache.set(streamCacheKey, {
|
|
2750
|
+
text,
|
|
2751
|
+
blocksMap
|
|
2647
2752
|
});
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
}
|
|
2652
|
-
const results = [];
|
|
2653
|
-
for (let i = 0; i < patches.length; i++) {
|
|
2654
|
-
if (resultsMap.has(i)) {
|
|
2655
|
-
results.push(resultsMap.get(i));
|
|
2656
|
-
} else {
|
|
2657
|
-
const match = patchMatches.find((m) => m.index === i);
|
|
2658
|
-
results.push({
|
|
2659
|
-
success: false,
|
|
2660
|
-
error: match ? match.error : `Block ${i + 1}: Unknown error.`
|
|
2661
|
-
});
|
|
2753
|
+
if (streamingBlocksCache.size > MAX_CACHE_SIZE) {
|
|
2754
|
+
const firstKey = streamingBlocksCache.keys().next().value;
|
|
2755
|
+
streamingBlocksCache.delete(firstKey);
|
|
2662
2756
|
}
|
|
2663
2757
|
}
|
|
2664
|
-
return
|
|
2758
|
+
return result;
|
|
2665
2759
|
};
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2760
|
+
TOOL_LABELS = {
|
|
2761
|
+
"write_file": "WriteFile",
|
|
2762
|
+
"update_file": "UpdateFile",
|
|
2763
|
+
"read_folder": "ReadFolder",
|
|
2764
|
+
"view_file": "ViewFile",
|
|
2765
|
+
"exec_command": "ExecuteCommand",
|
|
2766
|
+
"web_search": "WebSearch",
|
|
2767
|
+
"web_scrape": "ReadSite",
|
|
2768
|
+
"search_keyword": "SearchKeyword",
|
|
2769
|
+
"write_pdf": "CreatePDF",
|
|
2770
|
+
"write_docx": "CreateDocument",
|
|
2771
|
+
"generate_image": "GenerateImage",
|
|
2772
|
+
// PascalCase Support
|
|
2773
|
+
"WriteFile": "WriteFile",
|
|
2774
|
+
"PatchFile": "PatchFile",
|
|
2775
|
+
"ReadFolder": "ReadFolder",
|
|
2776
|
+
"ReadFile": "ReadFile",
|
|
2777
|
+
"Run": "RunCommand",
|
|
2778
|
+
"WebSearch": "WebSearch",
|
|
2779
|
+
"WebScrape": "WebScrape",
|
|
2780
|
+
"SearchKeyword": "SearchKeyword",
|
|
2781
|
+
"WritePDF": "WritePDF",
|
|
2782
|
+
"WriteDoc": "WriteDoc",
|
|
2783
|
+
"Memory": "Memory",
|
|
2784
|
+
"Chat": "Chat",
|
|
2785
|
+
"GenerateImage": "GenerateImage"
|
|
2786
|
+
};
|
|
2787
|
+
REGEX_INITIAL_THINK = /<\/think>(\r?\n){2}/gi;
|
|
2788
|
+
REGEX_INITIAL_TOOL = /(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|\s*turn\s*:))/gi;
|
|
2789
|
+
REGEX_SYSTEM = /\[SYSTEM\][\s\S]*?\[\/SYSTEM\]/gi;
|
|
2790
|
+
REGEX_THINK = /<(think|thought)>[\s\S]*?(?:<\/(think|thought)>|$)/gi;
|
|
2791
|
+
REGEX_ANSWER = /\[ANSWER\][\s\S]*?(?:\[\/ANSWER\]|$)/gi;
|
|
2792
|
+
REGEX_TOOL_RES = /\[TOOL RESULT\]:?\s*/gi;
|
|
2793
|
+
REGEX_SUCCESS_ERROR = /^\s*(SUCCESS|ERROR):.*(\r?\n)?/gm;
|
|
2794
|
+
REGEX_TURN_1 = /\[\s*turn\s*:\s*(continue|finish)\s*\]/gi;
|
|
2795
|
+
REGEX_END = /\[\[END\]\]/gi;
|
|
2796
|
+
REGEX_TURN_2 = /\[\s*turn\s*:?.*?$/gi;
|
|
2797
|
+
REGEX_TURN_3 = /\n\s*turn\s*:?.*?$/gi;
|
|
2798
|
+
REGEX_OPEN_BRACKET = /\[\s*$/gi;
|
|
2799
|
+
REGEX_RESPONDED = /\n\nResponded on .*/g;
|
|
2800
|
+
REGEX_PROMPTED = /\n\n\[Prompted on: .*\]/g;
|
|
2801
|
+
REGEX_ARROWS = /(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi;
|
|
2802
|
+
REGEX_ARROWS_L = /(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi;
|
|
2803
|
+
REGEX_ARROWS_U = /(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi;
|
|
2804
|
+
REGEX_ARROWS_D = /(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi;
|
|
2805
|
+
REGEX_ARROWS_LR = /(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi;
|
|
2806
|
+
REGEX_TERMINAL = /@\[TerminalName:.*?, ProcessId:.*?\]/gi;
|
|
2807
|
+
REGEX_TOOLS = /\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx|generate_image)\b/gi;
|
|
2808
|
+
cleanSignals = (text) => {
|
|
2809
|
+
if (!text) return text;
|
|
2810
|
+
let result = text.replace(REGEX_INITIAL_THINK, "</think>").replace(REGEX_INITIAL_TOOL, "");
|
|
2811
|
+
const trigger = "tool:functions.";
|
|
2812
|
+
if (result.toLowerCase().includes(trigger)) {
|
|
2813
|
+
while (true) {
|
|
2814
|
+
const lowerResult = result.toLowerCase();
|
|
2815
|
+
let triggerIdx = lowerResult.indexOf(trigger);
|
|
2816
|
+
if (triggerIdx === -1) break;
|
|
2817
|
+
let startIdx = triggerIdx;
|
|
2818
|
+
let hasOuterBracket = false;
|
|
2819
|
+
let k = triggerIdx - 1;
|
|
2820
|
+
while (k >= 0 && /\s/.test(result[k])) k--;
|
|
2821
|
+
if (k >= 0 && result[k] === "[") {
|
|
2822
|
+
startIdx = k;
|
|
2823
|
+
hasOuterBracket = true;
|
|
2685
2824
|
}
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2825
|
+
let balance = 0;
|
|
2826
|
+
let foundStart = false;
|
|
2827
|
+
let inString = null;
|
|
2828
|
+
let j = triggerIdx;
|
|
2829
|
+
while (j < result.length) {
|
|
2830
|
+
const char = result[j];
|
|
2831
|
+
if (!inString && (char === "'" || char === '"' || char === "`")) {
|
|
2832
|
+
inString = char;
|
|
2833
|
+
} else if (inString && char === inString && result[j - 1] !== "\\") {
|
|
2834
|
+
inString = null;
|
|
2696
2835
|
}
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
currentFinalLineIdx++;
|
|
2836
|
+
if (!inString) {
|
|
2837
|
+
if (char === "(") {
|
|
2838
|
+
balance++;
|
|
2839
|
+
foundStart = true;
|
|
2840
|
+
} else if (char === ")") {
|
|
2841
|
+
balance--;
|
|
2842
|
+
}
|
|
2705
2843
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2844
|
+
if (foundStart && balance === 0 && !inString) {
|
|
2845
|
+
let endIdx = j;
|
|
2846
|
+
if (hasOuterBracket) {
|
|
2847
|
+
let m = j + 1;
|
|
2848
|
+
while (m < result.length && /\s/.test(result[m])) m++;
|
|
2849
|
+
if (m < result.length && result[m] === "]") {
|
|
2850
|
+
endIdx = m;
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
result = result.substring(0, startIdx) + result.substring(endIdx + 1);
|
|
2854
|
+
break;
|
|
2855
|
+
}
|
|
2856
|
+
j++;
|
|
2857
|
+
if (j === result.length) {
|
|
2858
|
+
result = result.substring(0, startIdx);
|
|
2859
|
+
return result;
|
|
2711
2860
|
}
|
|
2712
2861
|
}
|
|
2713
2862
|
}
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2863
|
+
}
|
|
2864
|
+
return result.replaceAll(REGEX_SYSTEM, "").replaceAll(REGEX_THINK, "").replace(REGEX_ANSWER, "").replaceAll(REGEX_TOOL_RES, "").replaceAll(REGEX_SUCCESS_ERROR, "").replaceAll(REGEX_TURN_1, "").replaceAll(REGEX_END, "").replaceAll(REGEX_TURN_2, "").replaceAll(REGEX_TURN_3, "").replaceAll(REGEX_OPEN_BRACKET, "").replaceAll(REGEX_RESPONDED, "").replaceAll(REGEX_PROMPTED, "").replaceAll(REGEX_ARROWS, "\u2192").replaceAll(REGEX_ARROWS_L, "\u2190").replaceAll(REGEX_ARROWS_U, "\u2191").replaceAll(REGEX_ARROWS_D, "\u2193").replaceAll(REGEX_ARROWS_LR, "\u2194").replaceAll(REGEX_TERMINAL, "").replaceAll(REGEX_TOOLS, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
|
|
2865
|
+
};
|
|
2866
|
+
clearBlocksCache = () => {
|
|
2867
|
+
blocksCache.clear();
|
|
2868
|
+
streamingBlocksCache.clear();
|
|
2869
|
+
};
|
|
2870
|
+
}
|
|
2871
|
+
});
|
|
2872
|
+
|
|
2873
|
+
// src/components/MultilineInput.jsx
|
|
2874
|
+
import React2, { useState as useState2, useEffect as useEffect2, useMemo, useCallback, useRef } from "react";
|
|
2875
|
+
import { Box, Text as Text2, useInput } from "ink";
|
|
2876
|
+
function expandTabs(text, tabSize) {
|
|
2877
|
+
return text.replace(/\t/g, " ".repeat(tabSize));
|
|
2878
|
+
}
|
|
2879
|
+
function normalizeLineEndings(text) {
|
|
2880
|
+
if (text == null) return "";
|
|
2881
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
2882
|
+
}
|
|
2883
|
+
function formattedToRaw(formattedIdx, pasteBlocks, value) {
|
|
2884
|
+
let rawIdx = formattedIdx;
|
|
2885
|
+
const sortedBlocks = [...pasteBlocks].sort((a, b) => a.start - b.start);
|
|
2886
|
+
let currentFormattedOffset = 0;
|
|
2887
|
+
for (const block of sortedBlocks) {
|
|
2888
|
+
const formattedStart = block.start - currentFormattedOffset;
|
|
2889
|
+
const lines = normalizeLineEndings(block.text).split("\n").length;
|
|
2890
|
+
const chars = block.text.length;
|
|
2891
|
+
const placeholderLength = (lines > 3 ? `[Pasted ${lines} lines]` : `[Pasted ${chars} chars]`).length;
|
|
2892
|
+
const formattedEnd = formattedStart + placeholderLength;
|
|
2893
|
+
if (formattedIdx <= formattedStart) {
|
|
2894
|
+
break;
|
|
2895
|
+
} else if (formattedIdx < formattedEnd) {
|
|
2896
|
+
rawIdx = block.end;
|
|
2897
|
+
break;
|
|
2898
|
+
} else {
|
|
2899
|
+
const delta = block.text.length - placeholderLength;
|
|
2900
|
+
rawIdx += delta;
|
|
2901
|
+
currentFormattedOffset += delta;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
return Math.min(rawIdx, value.length);
|
|
2905
|
+
}
|
|
2906
|
+
function computeVisualMatrix(value, cursorIndex, wrapWidth, formatText, pasteBlocks = []) {
|
|
2907
|
+
const textBefore = (value || "").slice(0, cursorIndex);
|
|
2908
|
+
let visualCursorIdx = formatText(textBefore).length;
|
|
2909
|
+
let fullFormatted = formatText(value || "");
|
|
2910
|
+
const sortedBlocks = [...pasteBlocks].sort((a, b) => b.start - a.start);
|
|
2911
|
+
for (const block of sortedBlocks) {
|
|
2912
|
+
const formattedStart = formatText(value.slice(0, block.start)).length;
|
|
2913
|
+
const formattedPasted = formatText(block.text);
|
|
2914
|
+
const formattedEnd = formattedStart + formattedPasted.length;
|
|
2915
|
+
const lines = normalizeLineEndings(block.text).split("\n").length;
|
|
2916
|
+
const chars = block.text.length;
|
|
2917
|
+
const placeholderText = lines > 3 ? `[Pasted ${lines} lines]` : `[Pasted ${chars} chars]`;
|
|
2918
|
+
fullFormatted = fullFormatted.slice(0, formattedStart) + placeholderText + fullFormatted.slice(formattedEnd);
|
|
2919
|
+
if (visualCursorIdx > formattedStart && visualCursorIdx < formattedEnd) {
|
|
2920
|
+
visualCursorIdx = formattedStart + placeholderText.length;
|
|
2921
|
+
} else if (visualCursorIdx >= formattedEnd) {
|
|
2922
|
+
visualCursorIdx = visualCursorIdx - (formattedEnd - formattedStart) + placeholderText.length;
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
const literalLines = fullFormatted.split("\n");
|
|
2926
|
+
const visualLines = [];
|
|
2927
|
+
let currentIdx = 0;
|
|
2928
|
+
let cursorLine = 0;
|
|
2929
|
+
let cursorCol = 0;
|
|
2930
|
+
let foundCursor = false;
|
|
2931
|
+
for (let i = 0; i < literalLines.length; i++) {
|
|
2932
|
+
const line = literalLines[i];
|
|
2933
|
+
if (line.length === 0) {
|
|
2934
|
+
if (!foundCursor && visualCursorIdx === currentIdx) {
|
|
2935
|
+
cursorLine = visualLines.length;
|
|
2936
|
+
cursorCol = 0;
|
|
2937
|
+
foundCursor = true;
|
|
2938
|
+
}
|
|
2939
|
+
visualLines.push({ text: "", globalStart: formattedToRaw(currentIdx, pasteBlocks, value), formattedStart: currentIdx });
|
|
2940
|
+
currentIdx += 1;
|
|
2941
|
+
continue;
|
|
2942
|
+
}
|
|
2943
|
+
const wrapped = wrapText(line, wrapWidth);
|
|
2944
|
+
const wrappedLines = wrapped.split("\n");
|
|
2945
|
+
let lastMatchEnd = 0;
|
|
2946
|
+
const chunks = [];
|
|
2947
|
+
for (let j = 0; j < wrappedLines.length; j++) {
|
|
2948
|
+
const wLine = wrappedLines[j];
|
|
2949
|
+
const trimmed = wLine.trim();
|
|
2950
|
+
if (trimmed.length === 0) {
|
|
2951
|
+
const spaceLength = wLine.length || 1;
|
|
2952
|
+
chunks.push({
|
|
2953
|
+
text: wLine,
|
|
2954
|
+
start: lastMatchEnd,
|
|
2955
|
+
length: spaceLength
|
|
2718
2956
|
});
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
const
|
|
2724
|
-
const
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
break;
|
|
2731
|
-
}
|
|
2732
|
-
if (s === allLinesFinal.length - 1) hunkEndInFinal = allLinesFinal.length;
|
|
2957
|
+
lastMatchEnd += spaceLength;
|
|
2958
|
+
} else {
|
|
2959
|
+
const idx = line.indexOf(trimmed, lastMatchEnd);
|
|
2960
|
+
if (idx !== -1) {
|
|
2961
|
+
const start = lastMatchEnd;
|
|
2962
|
+
const nextTrimmed = j < wrappedLines.length - 1 ? wrappedLines[j + 1].trim() : "";
|
|
2963
|
+
let end = line.length;
|
|
2964
|
+
if (nextTrimmed.length > 0) {
|
|
2965
|
+
const nextIdx = line.indexOf(nextTrimmed, idx + trimmed.length);
|
|
2966
|
+
if (nextIdx !== -1) {
|
|
2967
|
+
end = nextIdx;
|
|
2733
2968
|
}
|
|
2734
|
-
} else {
|
|
2735
|
-
hunkEndInFinal = allLinesFinal.length;
|
|
2736
2969
|
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
currentFinalLineIdx++;
|
|
2970
|
+
chunks.push({
|
|
2971
|
+
text: line.slice(start, end),
|
|
2972
|
+
start,
|
|
2973
|
+
length: end - start
|
|
2974
|
+
});
|
|
2975
|
+
lastMatchEnd = end;
|
|
2976
|
+
} else {
|
|
2977
|
+
chunks.push({
|
|
2978
|
+
text: wLine,
|
|
2979
|
+
start: lastMatchEnd,
|
|
2980
|
+
length: wLine.length
|
|
2981
|
+
});
|
|
2982
|
+
lastMatchEnd += wLine.length;
|
|
2751
2983
|
}
|
|
2752
2984
|
}
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
const
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
const contentAndFooter = contentPart.split(footerMarker);
|
|
2764
|
-
const content = contentAndFooter[0]?.trim() || "";
|
|
2765
|
-
const footer = contentAndFooter[1] ? `${footerMarker}${contentAndFooter[1]}` : "";
|
|
2766
|
-
const codeLines = content.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
2767
|
-
const gutterWidth = String(codeLines.length).length;
|
|
2768
|
-
const completedBlocks2 = [];
|
|
2769
|
-
let activeBlock2 = null;
|
|
2770
|
-
codeLines.forEach((line, idx) => {
|
|
2771
|
-
const isLast = idx === codeLines.length - 1;
|
|
2772
|
-
const block = {
|
|
2773
|
-
key: `${msg.id || Date.now()}-write-line-${idx}`,
|
|
2774
|
-
msg,
|
|
2775
|
-
type: "write-line",
|
|
2776
|
-
text: line,
|
|
2777
|
-
gutterWidth,
|
|
2778
|
-
lineNum: idx + 1,
|
|
2779
|
-
isFirstLine: idx === 0,
|
|
2780
|
-
isLastLine: isLast
|
|
2781
|
-
};
|
|
2782
|
-
if (isLast && msg.isStreaming) {
|
|
2783
|
-
activeBlock2 = block;
|
|
2784
|
-
} else {
|
|
2785
|
-
completedBlocks2.push(block);
|
|
2786
|
-
}
|
|
2787
|
-
});
|
|
2788
|
-
return {
|
|
2789
|
-
completed: completedBlocks2,
|
|
2790
|
-
active: activeBlock2 ? [activeBlock2] : []
|
|
2791
|
-
};
|
|
2985
|
+
}
|
|
2986
|
+
for (let idx = 0; idx < chunks.length; idx++) {
|
|
2987
|
+
const chunkObj = chunks[idx];
|
|
2988
|
+
const chunk = chunkObj.text;
|
|
2989
|
+
const chunkStart = currentIdx + chunkObj.start;
|
|
2990
|
+
const chunkEnd = chunkStart + chunkObj.length;
|
|
2991
|
+
if (!foundCursor && visualCursorIdx >= chunkStart && (visualCursorIdx < chunkEnd || visualCursorIdx === chunkEnd && idx === chunks.length - 1)) {
|
|
2992
|
+
cursorLine = visualLines.length;
|
|
2993
|
+
cursorCol = visualCursorIdx - chunkStart;
|
|
2994
|
+
foundCursor = true;
|
|
2792
2995
|
}
|
|
2793
|
-
|
|
2794
|
-
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
activeBlock2 = block;
|
|
2811
|
-
} else {
|
|
2812
|
-
completedBlocks2.push(block);
|
|
2813
|
-
}
|
|
2996
|
+
visualLines.push({
|
|
2997
|
+
text: chunk,
|
|
2998
|
+
globalStart: formattedToRaw(chunkStart, pasteBlocks, value),
|
|
2999
|
+
formattedStart: chunkStart
|
|
3000
|
+
});
|
|
3001
|
+
}
|
|
3002
|
+
currentIdx += line.length + 1;
|
|
3003
|
+
}
|
|
3004
|
+
if (!foundCursor) {
|
|
3005
|
+
if (visualLines.length === 0) {
|
|
3006
|
+
visualLines.push({ text: "", globalStart: 0, formattedStart: 0 });
|
|
3007
|
+
} else {
|
|
3008
|
+
if (fullFormatted.endsWith("\n")) {
|
|
3009
|
+
visualLines.push({
|
|
3010
|
+
text: "",
|
|
3011
|
+
globalStart: formattedToRaw(currentIdx, pasteBlocks, value),
|
|
3012
|
+
formattedStart: currentIdx
|
|
2814
3013
|
});
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
3014
|
+
cursorLine = visualLines.length - 1;
|
|
3015
|
+
cursorCol = 0;
|
|
3016
|
+
} else {
|
|
3017
|
+
cursorLine = visualLines.length - 1;
|
|
3018
|
+
cursorCol = visualLines[cursorLine].text.length;
|
|
2819
3019
|
}
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
3020
|
+
}
|
|
3021
|
+
}
|
|
3022
|
+
return { visualLines, cursorLine, cursorCol };
|
|
3023
|
+
}
|
|
3024
|
+
var ControlledMultilineInput, MultilineInput;
|
|
3025
|
+
var init_MultilineInput = __esm({
|
|
3026
|
+
"src/components/MultilineInput.jsx"() {
|
|
3027
|
+
init_text();
|
|
3028
|
+
ControlledMultilineInput = ({
|
|
3029
|
+
value,
|
|
3030
|
+
rows,
|
|
3031
|
+
maxRows,
|
|
3032
|
+
highlightStyle,
|
|
3033
|
+
textStyle,
|
|
3034
|
+
placeholder = "",
|
|
3035
|
+
mask,
|
|
3036
|
+
showCursor = true,
|
|
3037
|
+
focus = true,
|
|
3038
|
+
tabSize = 4,
|
|
3039
|
+
cursorIndex = 0,
|
|
3040
|
+
highlight,
|
|
3041
|
+
columns = 80,
|
|
3042
|
+
pasteBlocks = []
|
|
3043
|
+
}) => {
|
|
3044
|
+
const scrollOffsetRef = useRef(0);
|
|
3045
|
+
const wrapWidth = useMemo(() => Math.max(20, columns - 10), [columns]);
|
|
3046
|
+
const formatText = useCallback(
|
|
3047
|
+
(text, isPlaceholder = false) => {
|
|
3048
|
+
const normalized = normalizeLineEndings(text);
|
|
3049
|
+
if (!isPlaceholder && mask) {
|
|
3050
|
+
return normalized.replace(/[^\n]/g, mask);
|
|
3051
|
+
}
|
|
3052
|
+
const expanded = expandTabs(normalized, tabSize);
|
|
3053
|
+
if (isPlaceholder) return expanded;
|
|
3054
|
+
return expanded.replace(/@\[(.*?)\]/g, (match, p1) => {
|
|
3055
|
+
const hashIdx = p1.indexOf("#");
|
|
3056
|
+
const colonIdx = p1.indexOf(":L");
|
|
3057
|
+
let pathOnly = p1;
|
|
3058
|
+
let suffix = "";
|
|
3059
|
+
if (hashIdx !== -1) {
|
|
3060
|
+
pathOnly = p1.slice(0, hashIdx);
|
|
3061
|
+
suffix = p1.slice(hashIdx);
|
|
3062
|
+
} else if (colonIdx !== -1) {
|
|
3063
|
+
pathOnly = p1.slice(0, colonIdx);
|
|
3064
|
+
suffix = p1.slice(colonIdx);
|
|
3065
|
+
}
|
|
3066
|
+
let rel = pathOnly.replace(/\\/g, "/");
|
|
3067
|
+
const cwd = (process.cwd() || "").replace(/\\/g, "/");
|
|
3068
|
+
if (cwd && rel.toLowerCase().startsWith(cwd.toLowerCase() + "/")) {
|
|
3069
|
+
rel = rel.slice(cwd.length + 1);
|
|
3070
|
+
} else if (rel.startsWith("./")) {
|
|
3071
|
+
rel = rel.slice(2);
|
|
3072
|
+
}
|
|
3073
|
+
const parts = rel.split("/");
|
|
3074
|
+
const basename = parts[parts.length - 1];
|
|
3075
|
+
return `[${basename}${suffix}]`;
|
|
3076
|
+
});
|
|
3077
|
+
},
|
|
3078
|
+
[tabSize, mask]
|
|
3079
|
+
);
|
|
3080
|
+
const { visualLines, cursorLine, cursorCol } = useMemo(() => {
|
|
3081
|
+
return computeVisualMatrix(value, cursorIndex, wrapWidth, formatText, pasteBlocks);
|
|
3082
|
+
}, [value, cursorIndex, wrapWidth, formatText, pasteBlocks]);
|
|
3083
|
+
const contentHeight = visualLines.length;
|
|
3084
|
+
const visibleRows = useMemo(() => {
|
|
3085
|
+
return Math.max(rows ?? maxRows ?? 1, Math.min(maxRows ?? rows ?? 1, contentHeight));
|
|
3086
|
+
}, [rows, maxRows, contentHeight]);
|
|
3087
|
+
const cursorLineEnd = cursorLine + 1;
|
|
3088
|
+
const viewportEnd = scrollOffsetRef.current + visibleRows;
|
|
3089
|
+
let newScrollOffset = scrollOffsetRef.current;
|
|
3090
|
+
if (cursorLineEnd <= scrollOffsetRef.current) {
|
|
3091
|
+
newScrollOffset = Math.max(0, cursorLineEnd - 1);
|
|
3092
|
+
} else if (cursorLineEnd > viewportEnd) {
|
|
3093
|
+
newScrollOffset = cursorLineEnd - visibleRows;
|
|
3094
|
+
} else if (contentHeight) {
|
|
3095
|
+
if (contentHeight < visibleRows) {
|
|
3096
|
+
newScrollOffset = 0;
|
|
3097
|
+
} else if (contentHeight < viewportEnd) {
|
|
3098
|
+
newScrollOffset = contentHeight - visibleRows;
|
|
3099
|
+
}
|
|
2830
3100
|
}
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
3101
|
+
scrollOffsetRef.current = newScrollOffset;
|
|
3102
|
+
const visibleLines = useMemo(() => {
|
|
3103
|
+
return visualLines.slice(newScrollOffset, newScrollOffset + visibleRows);
|
|
3104
|
+
}, [visualLines, newScrollOffset, visibleRows]);
|
|
3105
|
+
const [blink, setBlink] = useState2(true);
|
|
3106
|
+
useEffect2(() => {
|
|
3107
|
+
setBlink(true);
|
|
3108
|
+
if (!focus || !showCursor) return;
|
|
3109
|
+
const timer = setInterval(() => {
|
|
3110
|
+
setBlink((prev) => !prev);
|
|
3111
|
+
}, 530);
|
|
3112
|
+
return () => clearInterval(timer);
|
|
3113
|
+
}, [focus, showCursor, value, cursorIndex]);
|
|
3114
|
+
const cursorStyle = useMemo(() => ({
|
|
3115
|
+
...textStyle,
|
|
3116
|
+
color: showCursor && focus && blink ? "white" : void 0,
|
|
3117
|
+
bold: showCursor && focus && blink,
|
|
3118
|
+
inverse: showCursor && focus && blink
|
|
3119
|
+
}), [textStyle, showCursor, focus, blink]);
|
|
3120
|
+
const renderLineText = (text, isCursor, col, cStyle) => {
|
|
3121
|
+
if (!text) {
|
|
3122
|
+
const emptyText = placeholder && value.length === 0 ? formatText(placeholder, true) : "";
|
|
3123
|
+
if (isCursor) {
|
|
3124
|
+
const charAtCursor = emptyText[0] || " ";
|
|
3125
|
+
const right = emptyText.slice(1);
|
|
3126
|
+
return /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { ...cStyle }, charAtCursor), /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true }, right));
|
|
3127
|
+
}
|
|
3128
|
+
return /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true }, emptyText || " ");
|
|
3129
|
+
}
|
|
3130
|
+
const regex2 = /(\[Pasted \d+ (?:lines|chars)\])/g;
|
|
3131
|
+
const parts = text.split(regex2);
|
|
3132
|
+
let currentOffset = 0;
|
|
3133
|
+
const rendered = [];
|
|
3134
|
+
for (let i = 0; i < parts.length; i++) {
|
|
3135
|
+
const part = parts[i];
|
|
3136
|
+
if (part === "") continue;
|
|
3137
|
+
const isPlaceholder = part.match(/^\[Pasted \d+ (?:lines|chars)\]$/);
|
|
3138
|
+
const partLength = part.length;
|
|
3139
|
+
const partEnd = currentOffset + partLength;
|
|
3140
|
+
if (isCursor && col >= currentOffset && col < partEnd) {
|
|
3141
|
+
const localCol = col - currentOffset;
|
|
3142
|
+
const left = part.slice(0, localCol);
|
|
3143
|
+
const charAtCursor = part[localCol] || " ";
|
|
3144
|
+
const right = part.slice(localCol + 1);
|
|
3145
|
+
rendered.push(
|
|
3146
|
+
/* @__PURE__ */ React2.createElement(Text2, { key: i }, /* @__PURE__ */ React2.createElement(Text2, { color: isPlaceholder ? "magenta" : void 0 }, left), /* @__PURE__ */ React2.createElement(Text2, { ...cStyle }, charAtCursor), /* @__PURE__ */ React2.createElement(Text2, { color: isPlaceholder ? "magenta" : void 0 }, right))
|
|
3147
|
+
);
|
|
2852
3148
|
} else {
|
|
2853
|
-
|
|
3149
|
+
rendered.push(
|
|
3150
|
+
/* @__PURE__ */ React2.createElement(Text2, { key: i, color: isPlaceholder ? "magenta" : void 0 }, part)
|
|
3151
|
+
);
|
|
2854
3152
|
}
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
3153
|
+
currentOffset = partEnd;
|
|
3154
|
+
}
|
|
3155
|
+
if (isCursor && col >= text.length) {
|
|
3156
|
+
rendered.push(
|
|
3157
|
+
/* @__PURE__ */ React2.createElement(Text2, { key: "cursor-end", ...cStyle }, " ")
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
return /* @__PURE__ */ React2.createElement(React2.Fragment, null, rendered);
|
|
3161
|
+
};
|
|
3162
|
+
return /* @__PURE__ */ React2.createElement(Box, { height: visibleRows, width: wrapWidth + 1, overflow: "hidden", flexDirection: "column", flexGrow: 0, flexShrink: 0 }, visibleLines.map((lineObj, idx) => {
|
|
3163
|
+
const globalLineIdx = newScrollOffset + idx;
|
|
3164
|
+
const isCursorLine = globalLineIdx === cursorLine && focus && showCursor;
|
|
3165
|
+
return /* @__PURE__ */ React2.createElement(Text2, { key: globalLineIdx, ...textStyle, wrap: "truncate" }, renderLineText(lineObj.text, isCursorLine, cursorCol, cursorStyle));
|
|
3166
|
+
}));
|
|
3167
|
+
};
|
|
3168
|
+
MultilineInput = ({
|
|
3169
|
+
value,
|
|
3170
|
+
onChange,
|
|
3171
|
+
onSubmit,
|
|
3172
|
+
keyBindings,
|
|
3173
|
+
showCursor = true,
|
|
3174
|
+
highlightPastedText = false,
|
|
3175
|
+
focus = true,
|
|
3176
|
+
columns = 80,
|
|
3177
|
+
useCustomInput = (inputHandler, isActive) => useInput(inputHandler, { isActive }),
|
|
3178
|
+
onPasteStateChange,
|
|
3179
|
+
...controlledProps
|
|
3180
|
+
}) => {
|
|
3181
|
+
const [cursorIndex, setCursorIndex] = useState2(value.length);
|
|
3182
|
+
const [pasteLength, setPasteLength] = useState2(0);
|
|
3183
|
+
const [pasteBlocks, setPasteBlocks] = useState2([]);
|
|
3184
|
+
const cursorIndexRef = useRef(value.length);
|
|
3185
|
+
const valueRef = useRef(value);
|
|
3186
|
+
const pasteLengthRef = useRef(0);
|
|
3187
|
+
const pasteBlocksRef = useRef([]);
|
|
3188
|
+
const pasteBufferRef = useRef("");
|
|
3189
|
+
const pasteBufferStartRef = useRef(-1);
|
|
3190
|
+
const pasteTimerRef = useRef(null);
|
|
3191
|
+
const lastArrowTimeRef = useRef(0);
|
|
3192
|
+
cursorIndexRef.current = cursorIndex;
|
|
3193
|
+
valueRef.current = value;
|
|
3194
|
+
pasteLengthRef.current = pasteLength;
|
|
3195
|
+
pasteBlocksRef.current = pasteBlocks;
|
|
3196
|
+
useEffect2(() => {
|
|
3197
|
+
if (cursorIndexRef.current > value.length) {
|
|
3198
|
+
cursorIndexRef.current = value.length;
|
|
3199
|
+
setCursorIndex(value.length);
|
|
2863
3200
|
}
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
3201
|
+
if (!value) {
|
|
3202
|
+
setPasteBlocks([]);
|
|
3203
|
+
setPasteLength(0);
|
|
3204
|
+
} else {
|
|
3205
|
+
setPasteBlocks((prev) => prev.filter((b) => b.end <= value.length && b.start <= value.length));
|
|
3206
|
+
}
|
|
3207
|
+
}, [value]);
|
|
3208
|
+
useEffect2(() => {
|
|
3209
|
+
onPasteStateChange?.(pasteBlocks.length > 0);
|
|
3210
|
+
}, [pasteBlocks, onPasteStateChange]);
|
|
3211
|
+
const finalizePasteTransaction = () => {
|
|
3212
|
+
const accumulated = pasteBufferRef.current;
|
|
3213
|
+
const start = pasteBufferStartRef.current;
|
|
3214
|
+
const end = start + accumulated.length;
|
|
3215
|
+
const val = valueRef.current;
|
|
3216
|
+
const newValue = val.slice(0, start) + accumulated + val.slice(start);
|
|
3217
|
+
onChange(newValue);
|
|
3218
|
+
cursorIndexRef.current = end;
|
|
3219
|
+
setCursorIndex(end);
|
|
3220
|
+
setPasteLength(accumulated.length > 1 ? accumulated.length : 0);
|
|
3221
|
+
const lines = normalizeLineEndings(accumulated).split("\n").length;
|
|
3222
|
+
const chars = accumulated.length;
|
|
3223
|
+
if (chars > 50 && (lines > 3 || lines <= 3 && chars > 200)) {
|
|
3224
|
+
const newBlock = {
|
|
3225
|
+
start,
|
|
3226
|
+
end,
|
|
3227
|
+
text: accumulated
|
|
3228
|
+
};
|
|
3229
|
+
setPasteBlocks((prev) => {
|
|
3230
|
+
const delta = accumulated.length;
|
|
3231
|
+
const adjusted = prev.map((block) => {
|
|
3232
|
+
if (start <= block.start) {
|
|
3233
|
+
return {
|
|
3234
|
+
...block,
|
|
3235
|
+
start: block.start + delta,
|
|
3236
|
+
end: block.end + delta
|
|
2884
3237
|
};
|
|
2885
|
-
if (isLast && msg.isStreaming && inCodeBlock) {
|
|
2886
|
-
block.isActiveBlock = true;
|
|
2887
|
-
activeBlock = block;
|
|
2888
|
-
} else {
|
|
2889
|
-
completedBlocks.push(block);
|
|
2890
|
-
}
|
|
2891
|
-
codeLines = [];
|
|
2892
3238
|
}
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
3239
|
+
return block;
|
|
3240
|
+
});
|
|
3241
|
+
return [...adjusted, newBlock];
|
|
3242
|
+
});
|
|
3243
|
+
}
|
|
3244
|
+
pasteBufferRef.current = "";
|
|
3245
|
+
pasteBufferStartRef.current = -1;
|
|
3246
|
+
pasteTimerRef.current = null;
|
|
3247
|
+
};
|
|
3248
|
+
const flushPasteTransaction = () => {
|
|
3249
|
+
if (pasteTimerRef.current) {
|
|
3250
|
+
clearTimeout(pasteTimerRef.current);
|
|
3251
|
+
finalizePasteTransaction();
|
|
3252
|
+
}
|
|
3253
|
+
};
|
|
3254
|
+
useCustomInput((input, key) => {
|
|
3255
|
+
if (input === "\x1B[I" || input === "\x1B[O" || input === "[I" || input === "[O") {
|
|
3256
|
+
return;
|
|
3257
|
+
}
|
|
3258
|
+
let cleanInput = input;
|
|
3259
|
+
let isBracketedStart = false;
|
|
3260
|
+
let isBracketedEnd = false;
|
|
3261
|
+
if (cleanInput && typeof cleanInput === "string") {
|
|
3262
|
+
if (cleanInput.includes("\x1B[200~")) {
|
|
3263
|
+
isBracketedStart = true;
|
|
3264
|
+
cleanInput = cleanInput.replace(/\x1b\[200~/g, "");
|
|
3265
|
+
}
|
|
3266
|
+
if (cleanInput.includes("\x1B[201~")) {
|
|
3267
|
+
isBracketedEnd = true;
|
|
3268
|
+
cleanInput = cleanInput.replace(/\x1b\[201~/g, "");
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
const curIdx = cursorIndexRef.current;
|
|
3272
|
+
const val = valueRef.current;
|
|
3273
|
+
const currentPasteBlocks = pasteBlocksRef.current;
|
|
3274
|
+
const wrapWidth = Math.max(20, columns - 10);
|
|
3275
|
+
const adjustPasteBlocksOnEdit = (editStart, delta) => {
|
|
3276
|
+
if (currentPasteBlocks.length === 0) return;
|
|
3277
|
+
const updated = currentPasteBlocks.map((block) => {
|
|
3278
|
+
if (editStart <= block.start) {
|
|
3279
|
+
return {
|
|
3280
|
+
...block,
|
|
3281
|
+
start: block.start + delta,
|
|
3282
|
+
end: block.end + delta
|
|
2903
3283
|
};
|
|
2904
|
-
if (msg.isStreaming) {
|
|
2905
|
-
block.isActiveBlock = true;
|
|
2906
|
-
activeBlock = block;
|
|
2907
|
-
} else {
|
|
2908
|
-
completedBlocks.push(block);
|
|
2909
|
-
}
|
|
2910
|
-
}
|
|
2911
|
-
} else if (isTableRow) {
|
|
2912
|
-
inTable = true;
|
|
2913
|
-
tableLines.push(line);
|
|
2914
|
-
if (isLast) {
|
|
2915
|
-
if (msg.isStreaming) {
|
|
2916
|
-
activeBlock = {
|
|
2917
|
-
key: `${msg.id}-table-${idx}`,
|
|
2918
|
-
msg,
|
|
2919
|
-
type: "table",
|
|
2920
|
-
text: tableLines.join("\n"),
|
|
2921
|
-
isStreaming: true,
|
|
2922
|
-
isActiveBlock: true
|
|
2923
|
-
};
|
|
2924
|
-
} else {
|
|
2925
|
-
completedBlocks.push({
|
|
2926
|
-
key: `${msg.id}-table-${idx}`,
|
|
2927
|
-
msg,
|
|
2928
|
-
type: "table",
|
|
2929
|
-
text: tableLines.join("\n"),
|
|
2930
|
-
isStreaming: false
|
|
2931
|
-
});
|
|
2932
|
-
}
|
|
2933
3284
|
}
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
completedBlocks.push({
|
|
2937
|
-
key: `${msg.id}-table-${idx}`,
|
|
2938
|
-
msg,
|
|
2939
|
-
type: "table",
|
|
2940
|
-
text: tableLines.join("\n"),
|
|
2941
|
-
isStreaming: false
|
|
2942
|
-
});
|
|
2943
|
-
inTable = false;
|
|
2944
|
-
tableLines = [];
|
|
3285
|
+
if (editStart > block.start && editStart < block.end) {
|
|
3286
|
+
return null;
|
|
2945
3287
|
}
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
if (
|
|
2953
|
-
block.
|
|
2954
|
-
activeBlock = block;
|
|
2955
|
-
} else {
|
|
2956
|
-
completedBlocks.push(block);
|
|
3288
|
+
return block;
|
|
3289
|
+
}).filter(Boolean);
|
|
3290
|
+
setPasteBlocks(updated);
|
|
3291
|
+
};
|
|
3292
|
+
const adjustIndex = (idx) => {
|
|
3293
|
+
for (const block of currentPasteBlocks) {
|
|
3294
|
+
if (idx > block.start && idx < block.end) {
|
|
3295
|
+
return block.start;
|
|
2957
3296
|
}
|
|
2958
3297
|
}
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
type: "worked-duration",
|
|
2965
|
-
text: ""
|
|
2966
|
-
});
|
|
3298
|
+
return idx;
|
|
3299
|
+
};
|
|
3300
|
+
if (key.ctrl && (cleanInput === "o" || cleanInput === "")) {
|
|
3301
|
+
setPasteBlocks([]);
|
|
3302
|
+
return;
|
|
2967
3303
|
}
|
|
2968
|
-
|
|
2969
|
-
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
|
|
2973
|
-
|
|
2974
|
-
|
|
2975
|
-
|
|
2976
|
-
"update_file": "UpdateFile",
|
|
2977
|
-
"read_folder": "ReadFolder",
|
|
2978
|
-
"view_file": "ViewFile",
|
|
2979
|
-
"exec_command": "ExecuteCommand",
|
|
2980
|
-
"web_search": "WebSearch",
|
|
2981
|
-
"web_scrape": "ReadSite",
|
|
2982
|
-
"search_keyword": "SearchKeyword",
|
|
2983
|
-
"write_pdf": "CreatePDF",
|
|
2984
|
-
"write_docx": "CreateDocument",
|
|
2985
|
-
"generate_image": "GenerateImage",
|
|
2986
|
-
// PascalCase Support
|
|
2987
|
-
"WriteFile": "WriteFile",
|
|
2988
|
-
"PatchFile": "PatchFile",
|
|
2989
|
-
"ReadFolder": "ReadFolder",
|
|
2990
|
-
"ReadFile": "ReadFile",
|
|
2991
|
-
"Run": "RunCommand",
|
|
2992
|
-
"WebSearch": "WebSearch",
|
|
2993
|
-
"WebScrape": "WebScrape",
|
|
2994
|
-
"SearchKeyword": "SearchKeyword",
|
|
2995
|
-
"WritePDF": "WritePDF",
|
|
2996
|
-
"WriteDoc": "WriteDoc",
|
|
2997
|
-
"Memory": "Memory",
|
|
2998
|
-
"Chat": "Chat",
|
|
2999
|
-
"GenerateImage": "GenerateImage"
|
|
3000
|
-
};
|
|
3001
|
-
cleanSignals = (text) => {
|
|
3002
|
-
if (!text) return text;
|
|
3003
|
-
let result = text.replace(/<\/think>(\r?\n){2}/gi, "</think>").replace(/(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|\s*turn\s*:))/gi, "");
|
|
3004
|
-
const trigger = "tool:functions.";
|
|
3005
|
-
while (true) {
|
|
3006
|
-
const lowerResult = result.toLowerCase();
|
|
3007
|
-
let triggerIdx = lowerResult.indexOf(trigger);
|
|
3008
|
-
if (triggerIdx === -1) break;
|
|
3009
|
-
let startIdx = triggerIdx;
|
|
3010
|
-
let hasOuterBracket = false;
|
|
3011
|
-
let k = triggerIdx - 1;
|
|
3012
|
-
while (k >= 0 && /\s/.test(result[k])) k--;
|
|
3013
|
-
if (k >= 0 && result[k] === "[") {
|
|
3014
|
-
startIdx = k;
|
|
3015
|
-
hasOuterBracket = true;
|
|
3304
|
+
const isArrowKey = key.upArrow || key.downArrow || key.leftArrow || key.rightArrow;
|
|
3305
|
+
if (isArrowKey) {
|
|
3306
|
+
flushPasteTransaction();
|
|
3307
|
+
const now = Date.now();
|
|
3308
|
+
if (now - lastArrowTimeRef.current < 33) {
|
|
3309
|
+
return;
|
|
3310
|
+
}
|
|
3311
|
+
lastArrowTimeRef.current = now;
|
|
3016
3312
|
}
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3313
|
+
const submitKey = keyBindings?.submit ?? ((k) => k.return && k.ctrl);
|
|
3314
|
+
const newlineKey = keyBindings?.newline ?? ((k) => k.return);
|
|
3315
|
+
if (submitKey(key)) {
|
|
3316
|
+
flushPasteTransaction();
|
|
3317
|
+
onSubmit?.(val);
|
|
3318
|
+
return;
|
|
3319
|
+
} else if (newlineKey(key)) {
|
|
3320
|
+
flushPasteTransaction();
|
|
3321
|
+
adjustPasteBlocksOnEdit(curIdx, 1);
|
|
3322
|
+
const newValue = val.slice(0, curIdx) + "\n" + val.slice(curIdx);
|
|
3323
|
+
onChange(newValue);
|
|
3324
|
+
cursorIndexRef.current = curIdx + 1;
|
|
3325
|
+
setCursorIndex(curIdx + 1);
|
|
3326
|
+
setPasteLength(0);
|
|
3327
|
+
return;
|
|
3328
|
+
}
|
|
3329
|
+
if (key.tab || key.shift && key.tab || key.ctrl && cleanInput === "c") {
|
|
3330
|
+
return;
|
|
3331
|
+
}
|
|
3332
|
+
const identity = (t) => t;
|
|
3333
|
+
if (key.upArrow || key.downArrow) {
|
|
3334
|
+
flushPasteTransaction();
|
|
3335
|
+
if (showCursor) {
|
|
3336
|
+
const { visualLines, cursorLine, cursorCol } = computeVisualMatrix(val, curIdx, wrapWidth, identity, currentPasteBlocks);
|
|
3337
|
+
const targetLine = key.upArrow ? cursorLine - 1 : cursorLine + 1;
|
|
3338
|
+
if (targetLine >= 0 && targetLine < visualLines.length) {
|
|
3339
|
+
const targetLineObj = visualLines[targetLine];
|
|
3340
|
+
const targetCol = Math.min(cursorCol, targetLineObj.text.length);
|
|
3341
|
+
const targetFormattedIdx = targetLineObj.formattedStart + targetCol;
|
|
3342
|
+
let newIndex = formattedToRaw(targetFormattedIdx, currentPasteBlocks, val);
|
|
3343
|
+
newIndex = adjustIndex(newIndex);
|
|
3344
|
+
cursorIndexRef.current = newIndex;
|
|
3345
|
+
setCursorIndex(newIndex);
|
|
3346
|
+
setPasteLength(0);
|
|
3347
|
+
} else if (key.upArrow && cursorLine === 0) {
|
|
3348
|
+
cursorIndexRef.current = 0;
|
|
3349
|
+
setCursorIndex(0);
|
|
3350
|
+
setPasteLength(0);
|
|
3351
|
+
} else if (key.downArrow && cursorLine === visualLines.length - 1) {
|
|
3352
|
+
const lastLineObj = visualLines[visualLines.length - 1];
|
|
3353
|
+
const targetFormattedIdx = lastLineObj.formattedStart + lastLineObj.text.length;
|
|
3354
|
+
let newIndex = formattedToRaw(targetFormattedIdx, currentPasteBlocks, val);
|
|
3355
|
+
newIndex = adjustIndex(newIndex);
|
|
3356
|
+
cursorIndexRef.current = newIndex;
|
|
3357
|
+
setCursorIndex(newIndex);
|
|
3358
|
+
setPasteLength(0);
|
|
3359
|
+
}
|
|
3027
3360
|
}
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3361
|
+
} else if (key.leftArrow) {
|
|
3362
|
+
flushPasteTransaction();
|
|
3363
|
+
if (showCursor) {
|
|
3364
|
+
let newIndex = Math.max(0, curIdx - 1);
|
|
3365
|
+
const activeBlock = currentPasteBlocks.find((b) => curIdx === b.end);
|
|
3366
|
+
if (activeBlock) {
|
|
3367
|
+
newIndex = activeBlock.start;
|
|
3034
3368
|
}
|
|
3369
|
+
cursorIndexRef.current = newIndex;
|
|
3370
|
+
setCursorIndex(newIndex);
|
|
3371
|
+
setPasteLength(0);
|
|
3372
|
+
}
|
|
3373
|
+
} else if (key.rightArrow) {
|
|
3374
|
+
flushPasteTransaction();
|
|
3375
|
+
if (showCursor) {
|
|
3376
|
+
let newIndex = Math.min(val.length, curIdx + 1);
|
|
3377
|
+
const activeBlock = currentPasteBlocks.find((b) => curIdx === b.start);
|
|
3378
|
+
if (activeBlock) {
|
|
3379
|
+
newIndex = activeBlock.end;
|
|
3380
|
+
}
|
|
3381
|
+
cursorIndexRef.current = newIndex;
|
|
3382
|
+
setCursorIndex(newIndex);
|
|
3383
|
+
setPasteLength(0);
|
|
3384
|
+
}
|
|
3385
|
+
} else if (key.backspace) {
|
|
3386
|
+
flushPasteTransaction();
|
|
3387
|
+
const targetBlockIndex = currentPasteBlocks.findIndex((b) => curIdx === b.end);
|
|
3388
|
+
if (targetBlockIndex !== -1) {
|
|
3389
|
+
const targetBlock = currentPasteBlocks[targetBlockIndex];
|
|
3390
|
+
const delta = -(targetBlock.end - targetBlock.start);
|
|
3391
|
+
const newValue = val.slice(0, targetBlock.start) + val.slice(targetBlock.end);
|
|
3392
|
+
onChange(newValue);
|
|
3393
|
+
cursorIndexRef.current = targetBlock.start;
|
|
3394
|
+
setCursorIndex(targetBlock.start);
|
|
3395
|
+
setPasteLength(0);
|
|
3396
|
+
const updatedBlocks = currentPasteBlocks.filter((_, idx) => idx !== targetBlockIndex).map((block) => {
|
|
3397
|
+
if (block.start >= targetBlock.end) {
|
|
3398
|
+
return {
|
|
3399
|
+
...block,
|
|
3400
|
+
start: block.start + delta,
|
|
3401
|
+
end: block.end + delta
|
|
3402
|
+
};
|
|
3403
|
+
}
|
|
3404
|
+
return block;
|
|
3405
|
+
});
|
|
3406
|
+
setPasteBlocks(updatedBlocks);
|
|
3407
|
+
} else if (curIdx > 0) {
|
|
3408
|
+
adjustPasteBlocksOnEdit(curIdx - 1, -1);
|
|
3409
|
+
const newValue = val.slice(0, curIdx - 1) + val.slice(curIdx);
|
|
3410
|
+
onChange(newValue);
|
|
3411
|
+
cursorIndexRef.current = curIdx - 1;
|
|
3412
|
+
setCursorIndex(curIdx - 1);
|
|
3413
|
+
setPasteLength(0);
|
|
3035
3414
|
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3415
|
+
} else if (key.delete) {
|
|
3416
|
+
flushPasteTransaction();
|
|
3417
|
+
const targetBlockIndex = currentPasteBlocks.findIndex((b) => curIdx === b.start);
|
|
3418
|
+
if (targetBlockIndex !== -1) {
|
|
3419
|
+
const targetBlock = currentPasteBlocks[targetBlockIndex];
|
|
3420
|
+
const delta = -(targetBlock.end - targetBlock.start);
|
|
3421
|
+
const newValue = val.slice(0, targetBlock.start) + val.slice(targetBlock.end);
|
|
3422
|
+
onChange(newValue);
|
|
3423
|
+
setPasteLength(0);
|
|
3424
|
+
const updatedBlocks = currentPasteBlocks.filter((_, idx) => idx !== targetBlockIndex).map((block) => {
|
|
3425
|
+
if (block.start >= targetBlock.end) {
|
|
3426
|
+
return {
|
|
3427
|
+
...block,
|
|
3428
|
+
start: block.start + delta,
|
|
3429
|
+
end: block.end + delta
|
|
3430
|
+
};
|
|
3043
3431
|
}
|
|
3432
|
+
return block;
|
|
3433
|
+
});
|
|
3434
|
+
setPasteBlocks(updatedBlocks);
|
|
3435
|
+
} else {
|
|
3436
|
+
adjustPasteBlocksOnEdit(curIdx, -1);
|
|
3437
|
+
if (curIdx < val.length) {
|
|
3438
|
+
const newValue = val.slice(0, curIdx) + val.slice(curIdx + 1);
|
|
3439
|
+
onChange(newValue);
|
|
3440
|
+
setPasteLength(0);
|
|
3044
3441
|
}
|
|
3045
|
-
result = result.substring(0, startIdx) + result.substring(endIdx + 1);
|
|
3046
|
-
break;
|
|
3047
3442
|
}
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3443
|
+
} else if (key.home || key.end) {
|
|
3444
|
+
flushPasteTransaction();
|
|
3445
|
+
if (showCursor) {
|
|
3446
|
+
const { visualLines, cursorLine } = computeVisualMatrix(val, curIdx, wrapWidth, identity, currentPasteBlocks);
|
|
3447
|
+
const currentLineObj = visualLines[cursorLine];
|
|
3448
|
+
if (currentLineObj) {
|
|
3449
|
+
let newIndex;
|
|
3450
|
+
if (key.home) {
|
|
3451
|
+
newIndex = formattedToRaw(currentLineObj.formattedStart, currentPasteBlocks, val);
|
|
3452
|
+
} else if (key.end) {
|
|
3453
|
+
newIndex = formattedToRaw(currentLineObj.formattedStart + currentLineObj.text.length, currentPasteBlocks, val);
|
|
3454
|
+
}
|
|
3455
|
+
newIndex = adjustIndex(newIndex);
|
|
3456
|
+
cursorIndexRef.current = newIndex;
|
|
3457
|
+
setCursorIndex(newIndex);
|
|
3458
|
+
setPasteLength(0);
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
} else {
|
|
3462
|
+
if (cleanInput !== "" || isBracketedStart || isBracketedEnd) {
|
|
3463
|
+
const isPaste = isBracketedStart || isBracketedEnd || cleanInput.length > 1 || pasteTimerRef.current !== null;
|
|
3464
|
+
if (isPaste) {
|
|
3465
|
+
if (pasteTimerRef.current) {
|
|
3466
|
+
clearTimeout(pasteTimerRef.current);
|
|
3467
|
+
pasteBufferRef.current += cleanInput;
|
|
3468
|
+
} else {
|
|
3469
|
+
pasteBufferStartRef.current = curIdx;
|
|
3470
|
+
pasteBufferRef.current = cleanInput;
|
|
3471
|
+
}
|
|
3472
|
+
if (isBracketedEnd) {
|
|
3473
|
+
pasteTimerRef.current = null;
|
|
3474
|
+
finalizePasteTransaction();
|
|
3475
|
+
} else {
|
|
3476
|
+
pasteTimerRef.current = setTimeout(() => {
|
|
3477
|
+
finalizePasteTransaction();
|
|
3478
|
+
}, 100);
|
|
3479
|
+
}
|
|
3480
|
+
} else {
|
|
3481
|
+
adjustPasteBlocksOnEdit(curIdx, cleanInput.length);
|
|
3482
|
+
const newValue = val.slice(0, curIdx) + cleanInput + val.slice(curIdx);
|
|
3483
|
+
onChange(newValue);
|
|
3484
|
+
const newIndex = curIdx + cleanInput.length;
|
|
3485
|
+
cursorIndexRef.current = newIndex;
|
|
3486
|
+
setCursorIndex(newIndex);
|
|
3487
|
+
setPasteLength(0);
|
|
3488
|
+
}
|
|
3052
3489
|
}
|
|
3053
3490
|
}
|
|
3054
|
-
}
|
|
3055
|
-
return
|
|
3491
|
+
}, focus);
|
|
3492
|
+
return /* @__PURE__ */ React2.createElement(
|
|
3493
|
+
ControlledMultilineInput,
|
|
3494
|
+
{
|
|
3495
|
+
...controlledProps,
|
|
3496
|
+
value,
|
|
3497
|
+
cursorIndex,
|
|
3498
|
+
showCursor,
|
|
3499
|
+
focus,
|
|
3500
|
+
columns,
|
|
3501
|
+
pasteBlocks
|
|
3502
|
+
}
|
|
3503
|
+
);
|
|
3056
3504
|
};
|
|
3057
3505
|
}
|
|
3058
3506
|
});
|
|
3059
3507
|
|
|
3060
3508
|
// src/components/TerminalBox.jsx
|
|
3061
|
-
import React3 from "react";
|
|
3062
|
-
import { Box as Box2, Text as Text3 } from "ink";
|
|
3509
|
+
import React3, { useState as useState3 } from "react";
|
|
3510
|
+
import { Box as Box2, Text as Text3, useInput as useInput2 } from "ink";
|
|
3063
3511
|
var TerminalBox;
|
|
3064
3512
|
var init_TerminalBox = __esm({
|
|
3065
3513
|
"src/components/TerminalBox.jsx"() {
|
|
3066
3514
|
init_text();
|
|
3067
|
-
TerminalBox = React3.memo(({ command, output, completed = false, isFocused = false, columns = 80, isPty = false }) => {
|
|
3515
|
+
TerminalBox = React3.memo(({ command, output, completed = false, isFocused = false, columns = 80, isPty = false, terminalHeight = 24 }) => {
|
|
3068
3516
|
const processPTY = (text) => {
|
|
3069
3517
|
if (!text) return "";
|
|
3070
3518
|
const lines = [[]];
|
|
@@ -3188,6 +3636,18 @@ var init_TerminalBox = __esm({
|
|
|
3188
3636
|
};
|
|
3189
3637
|
const cleanOutput = processPTY(output).replace(/\n{3,}/g, "\n\n");
|
|
3190
3638
|
const displayOutput = isPty ? cleanOutput : cleanOutput ? wrapText(cleanOutput, columns - 6) : "";
|
|
3639
|
+
const [isExpanded, setIsExpanded] = useState3(false);
|
|
3640
|
+
useInput2((input, key) => {
|
|
3641
|
+
if (isFocused && key.ctrl && (input === "o" || input === "")) {
|
|
3642
|
+
setIsExpanded((prev) => !prev);
|
|
3643
|
+
}
|
|
3644
|
+
}, { isActive: isFocused });
|
|
3645
|
+
const rawLines = displayOutput ? displayOutput.split("\n") : [];
|
|
3646
|
+
const limit = Math.max(5, completed ? terminalHeight - 10 : terminalHeight - 20);
|
|
3647
|
+
const hasCollapsibleContent = rawLines.length > limit;
|
|
3648
|
+
const collapsedCount = rawLines.length - limit;
|
|
3649
|
+
const visibleLines = hasCollapsibleContent && !isExpanded ? rawLines.slice(rawLines.length - limit) : rawLines;
|
|
3650
|
+
const renderedOutput = visibleLines.join("\n");
|
|
3191
3651
|
return /* @__PURE__ */ React3.createElement(
|
|
3192
3652
|
Box2,
|
|
3193
3653
|
{
|
|
@@ -3205,7 +3665,7 @@ var init_TerminalBox = __esm({
|
|
|
3205
3665
|
width: "100%"
|
|
3206
3666
|
},
|
|
3207
3667
|
/* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React3.createElement(Box2, { flexShrink: 1, paddingRight: 2 }, /* @__PURE__ */ React3.createElement(Text3, null, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", bold: true }, completed ? "\u{1F3C1} FINISHED:" : "\u26A1 EXECUTING:", " "), /* @__PURE__ */ React3.createElement(Text3, { color: "white" }, command))), isPty && /* @__PURE__ */ React3.createElement(Box2, { flexShrink: 0, paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", bold: true }, "ADVANCE"))),
|
|
3208
|
-
displayOutput ? /* @__PURE__ */ React3.createElement(Box2, {
|
|
3668
|
+
displayOutput ? /* @__PURE__ */ React3.createElement(Box2, { flexDirection: "column", marginTop: 0, backgroundColor: isPty ? void 0 : "#0a0a0a", paddingX: 1 }, hasCollapsibleContent && !isExpanded && /* @__PURE__ */ React3.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "magenta" }, "...", collapsedCount, " lines collapsed... Press CTRL + O to expand.")), /* @__PURE__ */ React3.createElement(Text3, { color: completed ? "gray" : void 0 }, renderedOutput)) : !completed && /* @__PURE__ */ React3.createElement(Box2, { marginTop: 1, backgroundColor: isPty ? void 0 : "#0a0a0a", paddingX: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "white", italic: true }, "Waiting for output...")),
|
|
3209
3669
|
/* @__PURE__ */ React3.createElement(Box2, { justifyContent: "space-between", marginTop: 1 }, !completed ? /* @__PURE__ */ React3.createElement(Text3, { color: "gray", italic: true }, isFocused ? "Press TAB to unfocus, then double-press ESC to terminate." : "Double-press ESC to terminate if hanging.") : /* @__PURE__ */ React3.createElement(Box2, null), /* @__PURE__ */ React3.createElement(Text3, { color: "gray", bold: true }, completed ? "\u25CF ARCHIVED" : isFocused ? "\u25B6 TERMINAL FOCUSED" : "\u25CF LIVE (Press TAB to focus)"))
|
|
3210
3670
|
);
|
|
3211
3671
|
});
|
|
@@ -3482,78 +3942,17 @@ ${coloredArt[7]}`;
|
|
|
3482
3942
|
});
|
|
3483
3943
|
|
|
3484
3944
|
// src/components/ChatLayout.jsx
|
|
3485
|
-
import React4, { useState as
|
|
3945
|
+
import React4, { useState as useState4, useEffect as useEffect3, useRef as useRef2 } from "react";
|
|
3486
3946
|
import { Box as Box3, Text as Text4 } from "ink";
|
|
3487
3947
|
import { diffWordsWithSpace } from "diff";
|
|
3488
|
-
var useStreamingText, formatThinkText, parseMathSymbols, renderLatexText, InlineMarkdown, TableRenderer, MarkdownText,
|
|
3948
|
+
var useStreamingText, formatThinkText, REGEX_MD_TOKENS, REGEX_LATEX_FRAC, REGEX_LATEX_STYLE, parseMathSymbols, renderLatexText, InlineMarkdown, TableRenderer, MarkdownText, DiffLine, DiffBlock, CodeRenderer, formatThinkingDuration, MessageItem, BlockItem, ChatLayout;
|
|
3489
3949
|
var init_ChatLayout = __esm({
|
|
3490
3950
|
"src/components/ChatLayout.jsx"() {
|
|
3491
3951
|
init_TerminalBox();
|
|
3492
3952
|
init_text();
|
|
3493
3953
|
init_terminal();
|
|
3494
3954
|
useStreamingText = (targetText, isStreaming, isActiveBlock) => {
|
|
3495
|
-
|
|
3496
|
-
const targetTextRef = useRef2(targetText);
|
|
3497
|
-
useEffect3(() => {
|
|
3498
|
-
targetTextRef.current = targetText;
|
|
3499
|
-
}, [targetText]);
|
|
3500
|
-
useEffect3(() => {
|
|
3501
|
-
if (!isActiveBlock) {
|
|
3502
|
-
setDisplayedText(targetText);
|
|
3503
|
-
return;
|
|
3504
|
-
}
|
|
3505
|
-
if (!isStreaming && displayedText === targetText) {
|
|
3506
|
-
return;
|
|
3507
|
-
}
|
|
3508
|
-
const interval = setInterval(() => {
|
|
3509
|
-
setDisplayedText((current) => {
|
|
3510
|
-
const target = targetTextRef.current;
|
|
3511
|
-
if (current.length >= target.length) {
|
|
3512
|
-
if (!isStreaming) {
|
|
3513
|
-
clearInterval(interval);
|
|
3514
|
-
}
|
|
3515
|
-
return current;
|
|
3516
|
-
}
|
|
3517
|
-
if (!target.startsWith(current)) {
|
|
3518
|
-
return target;
|
|
3519
|
-
}
|
|
3520
|
-
const remaining = target.substring(current.length);
|
|
3521
|
-
const words = remaining.split(/(\s+)/);
|
|
3522
|
-
if (words.length <= 1) {
|
|
3523
|
-
if (!isStreaming) {
|
|
3524
|
-
clearInterval(interval);
|
|
3525
|
-
}
|
|
3526
|
-
return target;
|
|
3527
|
-
}
|
|
3528
|
-
const currentWordsCount = current.split(/\s+/).filter(Boolean).length;
|
|
3529
|
-
const targetWordsCount = target.split(/\s+/).filter(Boolean).length;
|
|
3530
|
-
const diff = targetWordsCount - currentWordsCount;
|
|
3531
|
-
let wordsToAdd = 1;
|
|
3532
|
-
if (diff > 15) {
|
|
3533
|
-
wordsToAdd = 4;
|
|
3534
|
-
} else if (diff > 8) {
|
|
3535
|
-
wordsToAdd = 3;
|
|
3536
|
-
} else if (diff > 3) {
|
|
3537
|
-
wordsToAdd = 2;
|
|
3538
|
-
}
|
|
3539
|
-
let addedText = "";
|
|
3540
|
-
let wordCount = 0;
|
|
3541
|
-
for (let i = 0; i < words.length; i++) {
|
|
3542
|
-
const w = words[i];
|
|
3543
|
-
addedText += w;
|
|
3544
|
-
if (/\S/.test(w)) {
|
|
3545
|
-
wordCount++;
|
|
3546
|
-
if (wordCount >= wordsToAdd) {
|
|
3547
|
-
break;
|
|
3548
|
-
}
|
|
3549
|
-
}
|
|
3550
|
-
}
|
|
3551
|
-
return current + addedText;
|
|
3552
|
-
});
|
|
3553
|
-
}, 100);
|
|
3554
|
-
return () => clearInterval(interval);
|
|
3555
|
-
}, [isStreaming, isActiveBlock, targetText, displayedText]);
|
|
3556
|
-
return displayedText;
|
|
3955
|
+
return targetText;
|
|
3557
3956
|
};
|
|
3558
3957
|
formatThinkText = (cleaned, columns = 80) => {
|
|
3559
3958
|
if (!cleaned) return null;
|
|
@@ -3581,14 +3980,17 @@ var init_ChatLayout = __esm({
|
|
|
3581
3980
|
return /* @__PURE__ */ React4.createElement(MarkdownText, { key: i, text: cleanPart, color: "gray", columns: availableWidth, italic: true });
|
|
3582
3981
|
}));
|
|
3583
3982
|
};
|
|
3983
|
+
REGEX_MD_TOKENS = /(```[\s\S]*?```|`[^`]+`|@\[.*?\]|\*\*.*?\*\*|\*.*?\*|\$.*?\$|\[.*?\]\s*\(.*?\)|\[.*?\]\s*\[.*?\]|https?:\/\/[^\s]+)/g;
|
|
3984
|
+
REGEX_LATEX_FRAC = /\\frac\s*\{([^{}]*)\}\s*\{([^{}]*)\}/g;
|
|
3985
|
+
REGEX_LATEX_STYLE = /(\\(?:mathbf|textbf|textit|underline|texttt)\{[^{}]*\})/g;
|
|
3584
3986
|
parseMathSymbols = (content) => {
|
|
3585
3987
|
return content.replace(/\\multiply|\\mul|\\times/g, "\xD7").replace(/\\div/g, "\xF7").replace(/\\cdot/g, "\u22C5").replace(/\\infty/g, "\u221E").replace(/\\pm/g, "\xB1").replace(/\\leq/g, "\u2264").replace(/\\geq/g, "\u2265").replace(/\\neq/g, "\u2260").replace(/\\sqrt\s*\{([^}]+)\}/g, "\u221A($1)").replace(/\\sqrt\s*(\w+|\d+)/g, "\u221A($1)").replace(/\\alpha/g, "\u03B1").replace(/\\beta/g, "\u03B2").replace(/\\theta/g, "\u03B8").replace(/\\pi/g, "\u03C0").replace(/\\approx/g, "\u2248").replace(/\\Delta/g, "\u0394").replace(/\\sigma/g, "\u03C3").replace(/\\sum/g, "\u03A3").replace(/\\prod/g, "\u03A0").replace(/\\rightarrow|\\to/g, "\u2192").replace(/\\left\b|\\right\b/g, "").replace(/\\left\(|\\right\)/g, (match) => match.includes("left") ? "(" : ")").replace(/\\left\[|\\right\]/g, (match) => match.includes("left") ? "[" : "]").replace(/\\\{|\\\}/g, (match) => match.includes("{") ? "{" : "}").replace(/\\text\s*\{([^}]+)\}/g, "$1").replace(/\\text\s+(\w+)/g, "$1").replace(/\\%/g, "%");
|
|
3586
3988
|
};
|
|
3587
3989
|
renderLatexText = (content, key) => {
|
|
3588
3990
|
if (!content) return null;
|
|
3589
|
-
let formatted = content.replace(
|
|
3991
|
+
let formatted = content.replace(REGEX_LATEX_FRAC, "($1/$2)");
|
|
3590
3992
|
formatted = parseMathSymbols(formatted);
|
|
3591
|
-
const parts = formatted.split(
|
|
3993
|
+
const parts = formatted.split(REGEX_LATEX_STYLE);
|
|
3592
3994
|
return /* @__PURE__ */ React4.createElement(React4.Fragment, { key }, parts.map((p, idx) => {
|
|
3593
3995
|
if (p.startsWith("\\")) {
|
|
3594
3996
|
const match = p.match(/\\(\w+)\{([^{}]*)\}/);
|
|
@@ -3607,7 +4009,7 @@ var init_ChatLayout = __esm({
|
|
|
3607
4009
|
};
|
|
3608
4010
|
InlineMarkdown = React4.memo(({ text, color, italic }) => {
|
|
3609
4011
|
if (!text) return null;
|
|
3610
|
-
const parts = text.split(
|
|
4012
|
+
const parts = text.split(REGEX_MD_TOKENS);
|
|
3611
4013
|
return /* @__PURE__ */ React4.createElement(Text4, { color, wrap: "anywhere", italic }, parts.map((part, j) => {
|
|
3612
4014
|
if (!part) return null;
|
|
3613
4015
|
if (part.startsWith("```") && part.endsWith("```")) {
|
|
@@ -3738,40 +4140,47 @@ var init_ChatLayout = __esm({
|
|
|
3738
4140
|
flushBuffers("final");
|
|
3739
4141
|
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: columns - 2 }, result);
|
|
3740
4142
|
});
|
|
3741
|
-
parseLineInfo = (l) => {
|
|
3742
|
-
if (!l) return null;
|
|
3743
|
-
const clean = l.replace("[UI_CONTEXT]", "").replace(/\r/g, "");
|
|
3744
|
-
const isR = clean.startsWith("-");
|
|
3745
|
-
const isA = clean.startsWith("+");
|
|
3746
|
-
let rest = isR || isA ? clean.substring(1) : clean;
|
|
3747
|
-
rest = rest.trim();
|
|
3748
|
-
const splitIdx = rest.indexOf("|");
|
|
3749
|
-
const num = splitIdx !== -1 ? rest.substring(0, splitIdx).trim() : "";
|
|
3750
|
-
const content = splitIdx !== -1 ? rest.substring(splitIdx + 1) : rest;
|
|
3751
|
-
return { isR, isA, num, content };
|
|
3752
|
-
};
|
|
3753
4143
|
DiffLine = React4.memo(({ line, pairContent, parentText, columns = 80 }) => {
|
|
3754
4144
|
const isContext = line.includes("[UI_CONTEXT]");
|
|
3755
4145
|
const cleanLine = line.replace("[UI_CONTEXT]", "");
|
|
3756
4146
|
if (isContext && cleanLine.includes("\u2550")) {
|
|
3757
|
-
return /* @__PURE__ */ React4.createElement(Box3, { paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "\u2550".repeat(Math.max(10, columns - 4))));
|
|
4147
|
+
return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, "\u2550".repeat(Math.max(10, columns - 4))));
|
|
3758
4148
|
}
|
|
3759
4149
|
const parsedCurrent = parseLineInfo(line);
|
|
3760
4150
|
if (!parsedCurrent) {
|
|
3761
4151
|
return /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: columns }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0 }), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, wrapText(cleanLine, columns - 14))));
|
|
3762
4152
|
}
|
|
3763
4153
|
const { isR: isRemoval, isA: isAddition, num: lineNum, content } = parsedCurrent;
|
|
3764
|
-
const innerBgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : void 0;
|
|
3765
4154
|
let finalPairContent = pairContent;
|
|
3766
4155
|
if (!finalPairContent && parentText && (isRemoval || isAddition)) {
|
|
3767
|
-
const
|
|
3768
|
-
const
|
|
3769
|
-
const
|
|
3770
|
-
|
|
3771
|
-
return
|
|
4156
|
+
const match = parentText.match(/\[DIFF_START\]([\s\S]*?)(?:\[DIFF_END\]|$)/);
|
|
4157
|
+
const diffBody = match ? match[1].trim() : "";
|
|
4158
|
+
const diffLines = diffBody.split("\n").map((l) => l.replace(/\r$/, ""));
|
|
4159
|
+
const parsedLines = diffLines.map((l) => {
|
|
4160
|
+
return {
|
|
4161
|
+
line: l,
|
|
4162
|
+
parsed: parseLineInfo(l),
|
|
4163
|
+
pairContent: null
|
|
4164
|
+
};
|
|
3772
4165
|
});
|
|
3773
|
-
|
|
3774
|
-
|
|
4166
|
+
let currentGroup = [];
|
|
4167
|
+
for (let idx = 0; idx < parsedLines.length; idx++) {
|
|
4168
|
+
const item = parsedLines[idx];
|
|
4169
|
+
if (item.parsed && (item.parsed.isR || item.parsed.isA)) {
|
|
4170
|
+
currentGroup.push(item);
|
|
4171
|
+
} else {
|
|
4172
|
+
if (currentGroup.length > 0) {
|
|
4173
|
+
alignChangeGroup(currentGroup);
|
|
4174
|
+
currentGroup = [];
|
|
4175
|
+
}
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
if (currentGroup.length > 0) {
|
|
4179
|
+
alignChangeGroup(currentGroup);
|
|
4180
|
+
}
|
|
4181
|
+
const matchedItem = parsedLines.find((item) => item.parsed && item.parsed.num === lineNum && item.parsed.isR === isRemoval);
|
|
4182
|
+
if (matchedItem) {
|
|
4183
|
+
finalPairContent = matchedItem.pairContent;
|
|
3775
4184
|
}
|
|
3776
4185
|
}
|
|
3777
4186
|
let words = [];
|
|
@@ -3786,7 +4195,7 @@ var init_ChatLayout = __esm({
|
|
|
3786
4195
|
}
|
|
3787
4196
|
const hasInlineChange = words.some((part) => isRemoval && part.removed || isAddition && part.added);
|
|
3788
4197
|
const isPureUnpairedBlock = !finalPairContent && (isRemoval || isAddition);
|
|
3789
|
-
const
|
|
4198
|
+
const innerBgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : void 0;
|
|
3790
4199
|
const finalNumColor = isRemoval || isAddition ? isRemoval ? "#d96868" : "#68d98c" : "gray";
|
|
3791
4200
|
const finalPrefixColor = isRemoval ? "#ff4d4d" : "#4dff88";
|
|
3792
4201
|
const displayPrefix = isRemoval ? "-" : isAddition ? "+" : " ";
|
|
@@ -3796,7 +4205,7 @@ var init_ChatLayout = __esm({
|
|
|
3796
4205
|
return /* @__PURE__ */ React4.createElement(Text4, { color: blockColor }, wrapText(content, columns - 14));
|
|
3797
4206
|
}
|
|
3798
4207
|
if (!(isRemoval || isAddition) || words.length === 0 || !hasInlineChange) {
|
|
3799
|
-
const textColor = isRemoval ? "#
|
|
4208
|
+
const textColor = isRemoval ? "#885555" : isAddition ? "#558866" : "gray";
|
|
3800
4209
|
return /* @__PURE__ */ React4.createElement(Text4, { color: textColor }, wrapText(content, columns - 14));
|
|
3801
4210
|
}
|
|
3802
4211
|
return /* @__PURE__ */ React4.createElement(Text4, { wrap: "anywhere" }, words.map((part, idx) => {
|
|
@@ -3807,7 +4216,7 @@ var init_ChatLayout = __esm({
|
|
|
3807
4216
|
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#ff3333" }, part.value);
|
|
3808
4217
|
}
|
|
3809
4218
|
if (part.added) return null;
|
|
3810
|
-
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#
|
|
4219
|
+
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#885555" }, part.value);
|
|
3811
4220
|
}
|
|
3812
4221
|
if (isAddition) {
|
|
3813
4222
|
const isSurroundedByAddition = words[idx - 1]?.added || words[idx + 1]?.added;
|
|
@@ -3815,7 +4224,7 @@ var init_ChatLayout = __esm({
|
|
|
3815
4224
|
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#33ff66" }, part.value);
|
|
3816
4225
|
}
|
|
3817
4226
|
if (part.removed) return null;
|
|
3818
|
-
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#
|
|
4227
|
+
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "#558866" }, part.value);
|
|
3819
4228
|
}
|
|
3820
4229
|
return /* @__PURE__ */ React4.createElement(Text4, { key: idx, color: "gray" }, part.value);
|
|
3821
4230
|
}));
|
|
@@ -3826,7 +4235,37 @@ var init_ChatLayout = __esm({
|
|
|
3826
4235
|
const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
|
|
3827
4236
|
const diffBody = match ? match[1].trim() : "";
|
|
3828
4237
|
const diffLines = diffBody.split("\n");
|
|
3829
|
-
|
|
4238
|
+
const parsedLines = diffLines.map((line) => {
|
|
4239
|
+
return {
|
|
4240
|
+
line,
|
|
4241
|
+
parsed: parseLineInfo(line),
|
|
4242
|
+
pairContent: null
|
|
4243
|
+
};
|
|
4244
|
+
});
|
|
4245
|
+
let currentGroup = [];
|
|
4246
|
+
for (let i = 0; i < parsedLines.length; i++) {
|
|
4247
|
+
const item = parsedLines[i];
|
|
4248
|
+
if (item.parsed && (item.parsed.isR || item.parsed.isA)) {
|
|
4249
|
+
currentGroup.push(item);
|
|
4250
|
+
} else {
|
|
4251
|
+
if (currentGroup.length > 0) {
|
|
4252
|
+
alignChangeGroup(currentGroup);
|
|
4253
|
+
currentGroup = [];
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
if (currentGroup.length > 0) {
|
|
4258
|
+
alignChangeGroup(currentGroup);
|
|
4259
|
+
}
|
|
4260
|
+
return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: columns - 3, marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingY: 0, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0 }), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " "))), parsedLines.map((item, i) => /* @__PURE__ */ React4.createElement(
|
|
4261
|
+
DiffLine,
|
|
4262
|
+
{
|
|
4263
|
+
key: i,
|
|
4264
|
+
line: item.line,
|
|
4265
|
+
pairContent: item.pairContent,
|
|
4266
|
+
columns: columns - 3
|
|
4267
|
+
}
|
|
4268
|
+
)), /* @__PURE__ */ React4.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: 3, flexShrink: 0 }), /* @__PURE__ */ React4.createElement(Box3, { width: 1, flexShrink: 0, marginLeft: 1 }), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React4.createElement(Text4, null, " ")))));
|
|
3830
4269
|
});
|
|
3831
4270
|
CodeRenderer = React4.memo(({ text, columns = 80 }) => {
|
|
3832
4271
|
if (!text) return null;
|
|
@@ -3887,7 +4326,7 @@ var init_ChatLayout = __esm({
|
|
|
3887
4326
|
paddingRight: 0,
|
|
3888
4327
|
width: "100%"
|
|
3889
4328
|
},
|
|
3890
|
-
/* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", bold: true }, "\
|
|
4329
|
+
/* @__PURE__ */ React4.createElement(Box3, { marginBottom: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray", bold: true }, "\u25B6_ ", lang.toUpperCase() || "CODE")),
|
|
3891
4330
|
/* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React4.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React4.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React4.createElement(Text4, { color: "gray" }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React4.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React4.createElement(Text4, { color: "#fcfca4ff" }, line)))))
|
|
3892
4331
|
);
|
|
3893
4332
|
}
|
|
@@ -4214,12 +4653,35 @@ var init_ChatLayout = __esm({
|
|
|
4214
4653
|
// src/components/StatusBar.jsx
|
|
4215
4654
|
import React5 from "react";
|
|
4216
4655
|
import { Box as Box4, Text as Text5 } from "ink";
|
|
4656
|
+
import { useState as useState5, useEffect as useEffect4 } from "react";
|
|
4217
4657
|
var StatusBar, StatusBar_default;
|
|
4218
4658
|
var init_StatusBar = __esm({
|
|
4219
4659
|
"src/components/StatusBar.jsx"() {
|
|
4220
4660
|
init_text();
|
|
4221
4661
|
StatusBar = React5.memo(({ mode, thinkingLevel, tokens = "0.0k", tokensTotal = "0.0k", chatId = "NEW-SESSION", isMemoryEnabled = true, apiTier = "Free", aiProvider = "Google" }) => {
|
|
4222
4662
|
const modeIcon = mode === "Flux" ? "" : "";
|
|
4663
|
+
const [memoryUsage, setMemoryUsage] = useState5(0);
|
|
4664
|
+
const [memoryLimit, setMemoryLimit] = useState5(0);
|
|
4665
|
+
const [memoryUnit, setMemoryUnit] = useState5("MB");
|
|
4666
|
+
useEffect4(() => {
|
|
4667
|
+
const getMemoryInfo = () => {
|
|
4668
|
+
const usage = process.memoryUsage();
|
|
4669
|
+
const isGB = usage.heapTotal / (1024 * 1024) >= 1024;
|
|
4670
|
+
const currentUnit = isGB ? "GB" : "MB";
|
|
4671
|
+
const formatToNumber = (bytes, toGB) => {
|
|
4672
|
+
const converted = bytes / (1024 * 1024 * (toGB ? 1024 : 1));
|
|
4673
|
+
return toGB ? parseFloat(converted.toFixed(2)) : Math.round(converted);
|
|
4674
|
+
};
|
|
4675
|
+
setMemoryUnit(currentUnit);
|
|
4676
|
+
setMemoryLimit(formatToNumber(usage.heapTotal, isGB));
|
|
4677
|
+
setMemoryUsage(formatToNumber(usage.heapUsed, isGB));
|
|
4678
|
+
};
|
|
4679
|
+
getMemoryInfo();
|
|
4680
|
+
const interval = setInterval(() => {
|
|
4681
|
+
getMemoryInfo();
|
|
4682
|
+
}, 3e3);
|
|
4683
|
+
return () => clearInterval(interval);
|
|
4684
|
+
}, []);
|
|
4223
4685
|
let maxLimit = 256e3;
|
|
4224
4686
|
if (aiProvider === "DeepSeek" || aiProvider === "Google" && apiTier === "Paid") {
|
|
4225
4687
|
maxLimit = 4e5;
|
|
@@ -4234,7 +4696,7 @@ var init_StatusBar = __esm({
|
|
|
4234
4696
|
},
|
|
4235
4697
|
/* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Box4, { marginRight: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, modeIcon, " ", mode.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, thinkingLevel.toUpperCase())), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray" }, "MEM: "), /* @__PURE__ */ React5.createElement(Text5, { color: "white", bold: true }, isMemoryEnabled ? "ON" : "OFF"))),
|
|
4236
4698
|
/* @__PURE__ */ React5.createElement(Box4, { flexGrow: 1, justifyContent: "center", paddingX: 2 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white", italic: true }, " ", truncatePath(process.cwd(), 35))),
|
|
4237
|
-
/* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, " ", formatTokens(tokensTotal), " ", /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, (tokens / maxLimit * 100).toFixed(0), "%"))), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", italic: true }, " ", chatId), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, " | ", /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "CUSTOM"))))
|
|
4699
|
+
/* @__PURE__ */ React5.createElement(Box4, null, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, " ", formatTokens(tokensTotal), " ", /* @__PURE__ */ React5.createElement(Text5, { dimColor: true }, (tokens / maxLimit * 100).toFixed(0), "%"))), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginX: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "grey", bold: true }, memoryUsage, "/", memoryLimit, " ", memoryUnit)), /* @__PURE__ */ React5.createElement(Text5, { color: "gray", dimColor: true }, "\u2503 "), /* @__PURE__ */ React5.createElement(Box4, { marginLeft: 1 }, /* @__PURE__ */ React5.createElement(Text5, { color: "gray", italic: true }, " ", chatId), (apiTier === "Custom" || apiTier === "Paid") && /* @__PURE__ */ React5.createElement(Text5, { color: "white" }, " | ", /* @__PURE__ */ React5.createElement(Text5, { color: "gray", bold: true }, "CUSTOM"))))
|
|
4238
4700
|
);
|
|
4239
4701
|
});
|
|
4240
4702
|
StatusBar_default = StatusBar;
|
|
@@ -4453,7 +4915,6 @@ var init_main_tools = __esm({
|
|
|
4453
4915
|
TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider) => `
|
|
4454
4916
|
-- TOOL DEFINITIONS --
|
|
4455
4917
|
Internal tools. **MUST use the EXACT syntax** [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
|
|
4456
|
-
NO TOOL CALL INSIDE THINKING
|
|
4457
4918
|
|
|
4458
4919
|
**TOOL USAGE POLICY:**
|
|
4459
4920
|
- **MAX 3 TOOL CALLS PER TURN${mode === "Flux" ? " (EXCEPTION FOR Todo TOOL: 3+ CALLS ALLOWED, Run: Limit 1 OR 2 CONSECUTIVE Run)" : ""}. Next Turn, verify tool results, plan next**
|
|
@@ -4471,8 +4932,8 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
|
|
|
4471
4932
|
3. [tool:functions.FileMap(path="path/file")]. Shows file structure, functions, class, import/export, variable
|
|
4472
4933
|
4. [tool:functions.PatchFile(path="...", replaceContent1="full line/block", newContent1="...", ...MAX 6)]. Surgical Patch. **Multiple patch on same file/path? Use replaceContent2, newContent2 etc >>> multiple spams**. Unsure? ReadFile >> guessing. **MUST VERIFY DIFF**
|
|
4473
4934
|
5. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile. Verify Imports
|
|
4474
|
-
6. [tool:functions.SearchKeyword(keyword="...", file="optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit
|
|
4475
|
-
7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ?
|
|
4935
|
+
6. [tool:functions.SearchKeyword(keyword="...", file="optional", subString="true/false optional")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file. Usage: Can search for relevent lines/logic area to read specifically for edit
|
|
4936
|
+
7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops -> Ask user
|
|
4476
4937
|
8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, Markdown IN ARRAY NOT ALLOWED. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed`.trim() : `- CREATIVE TOOLS (path = relative to CWD & WILL BE FIRST ARGUMENT, path separator: '/') -
|
|
4477
4938
|
1. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout
|
|
4478
4939
|
2. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document
|
|
@@ -5130,9 +5591,10 @@ ${finalOutput}`);
|
|
|
5130
5591
|
});
|
|
5131
5592
|
|
|
5132
5593
|
// src/components/SettingsMenu.jsx
|
|
5133
|
-
import React7, { useState as
|
|
5134
|
-
import { Box as Box6, Text as Text7, useInput as
|
|
5594
|
+
import React7, { useState as useState6, useEffect as useEffect5 } from "react";
|
|
5595
|
+
import { Box as Box6, Text as Text7, useInput as useInput3 } from "ink";
|
|
5135
5596
|
import TextInput from "ink-text-input";
|
|
5597
|
+
import v8 from "v8";
|
|
5136
5598
|
function SettingsMenu({
|
|
5137
5599
|
systemSettings,
|
|
5138
5600
|
setSystemSettings,
|
|
@@ -5144,11 +5606,34 @@ function SettingsMenu({
|
|
|
5144
5606
|
setMessages,
|
|
5145
5607
|
aiProvider
|
|
5146
5608
|
}) {
|
|
5147
|
-
const [activeColumn, setActiveColumn] =
|
|
5148
|
-
const [selectedCategoryIndex, setSelectedCategoryIndex] =
|
|
5149
|
-
const [selectedItemIndex, setSelectedItemIndex] =
|
|
5150
|
-
const [editingItem, setEditingItem] =
|
|
5151
|
-
const [editValue, setEditValue] =
|
|
5609
|
+
const [activeColumn, setActiveColumn] = useState6("categories");
|
|
5610
|
+
const [selectedCategoryIndex, setSelectedCategoryIndex] = useState6(0);
|
|
5611
|
+
const [selectedItemIndex, setSelectedItemIndex] = useState6(0);
|
|
5612
|
+
const [editingItem, setEditingItem] = useState6(null);
|
|
5613
|
+
const [editValue, setEditValue] = useState6("");
|
|
5614
|
+
const [currentMemory, setCurrentMemory] = useState6(0);
|
|
5615
|
+
const [maxMemory, setMaxMemory] = useState6(0);
|
|
5616
|
+
const [memoryUnit, setMemoryUnit] = useState6("MB");
|
|
5617
|
+
useEffect5(() => {
|
|
5618
|
+
const maxLimitBytes = v8.getHeapStatistics().heap_size_limit;
|
|
5619
|
+
const isGB = maxLimitBytes >= 1024 * 1024 * 1024;
|
|
5620
|
+
const unitLabel = isGB ? "GB" : "MB";
|
|
5621
|
+
const divisor = isGB ? 1024 * 1024 * 1024 : 1024 * 1024;
|
|
5622
|
+
setMaxMemory(parseFloat((maxLimitBytes / divisor).toFixed(2)));
|
|
5623
|
+
setMemoryUnit(unitLabel);
|
|
5624
|
+
const getMemoryStats = () => {
|
|
5625
|
+
const usage = process.memoryUsage();
|
|
5626
|
+
const targetBytes = usage.rss;
|
|
5627
|
+
const converted = targetBytes / divisor;
|
|
5628
|
+
const formattedCurrent = isGB ? parseFloat(converted.toFixed(2)) : Math.round(converted);
|
|
5629
|
+
setCurrentMemory(formattedCurrent);
|
|
5630
|
+
};
|
|
5631
|
+
getMemoryStats();
|
|
5632
|
+
const interval = setInterval(() => {
|
|
5633
|
+
getMemoryStats();
|
|
5634
|
+
}, 5e3);
|
|
5635
|
+
return () => clearInterval(interval);
|
|
5636
|
+
}, []);
|
|
5152
5637
|
const getCategoryItems = (catId) => {
|
|
5153
5638
|
switch (catId) {
|
|
5154
5639
|
case "memory":
|
|
@@ -5186,7 +5671,7 @@ function SettingsMenu({
|
|
|
5186
5671
|
};
|
|
5187
5672
|
const currentCatId = CATEGORIES[selectedCategoryIndex].id;
|
|
5188
5673
|
const currentItems = getCategoryItems(currentCatId);
|
|
5189
|
-
|
|
5674
|
+
useInput3((input, key) => {
|
|
5190
5675
|
if (editingItem) {
|
|
5191
5676
|
if (key.escape) {
|
|
5192
5677
|
setEditingItem(null);
|
|
@@ -5408,7 +5893,10 @@ function SettingsMenu({
|
|
|
5408
5893
|
});
|
|
5409
5894
|
if (currentCatId === "other") {
|
|
5410
5895
|
elements.push(
|
|
5411
|
-
/* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop:
|
|
5896
|
+
/* @__PURE__ */ React7.createElement(Box6, { key: "pty-notice", marginTop: 17, paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "white" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
|
|
5897
|
+
);
|
|
5898
|
+
elements.push(
|
|
5899
|
+
/* @__PURE__ */ React7.createElement(Box6, { key: "memory-load-2026", paddingX: 1 }, /* @__PURE__ */ React7.createElement(Text7, { color: "gray" }, "Memory Load: ", currentMemory, "/", maxMemory, " ", memoryUnit))
|
|
5412
5900
|
);
|
|
5413
5901
|
}
|
|
5414
5902
|
if (hasConflict) {
|
|
@@ -5451,13 +5939,13 @@ var init_SettingsMenu = __esm({
|
|
|
5451
5939
|
});
|
|
5452
5940
|
|
|
5453
5941
|
// src/components/ProfileForm.jsx
|
|
5454
|
-
import React8, { useState as
|
|
5942
|
+
import React8, { useState as useState7, useEffect as useEffect6 } from "react";
|
|
5455
5943
|
import { Box as Box7, Text as Text8 } from "ink";
|
|
5456
5944
|
import TextInput2 from "ink-text-input";
|
|
5457
5945
|
function ProfileForm({ initialData, onSave, onCancel }) {
|
|
5458
|
-
const [step, setStep] =
|
|
5459
|
-
const [currentInput, setCurrentInput] =
|
|
5460
|
-
const [profile, setProfile] =
|
|
5946
|
+
const [step, setStep] = useState7(0);
|
|
5947
|
+
const [currentInput, setCurrentInput] = useState7("");
|
|
5948
|
+
const [profile, setProfile] = useState7(() => ({
|
|
5461
5949
|
name: initialData?.name || "",
|
|
5462
5950
|
nickname: initialData?.nickname || "",
|
|
5463
5951
|
instructions: initialData?.instructions || ""
|
|
@@ -5467,7 +5955,7 @@ function ProfileForm({ initialData, onSave, onCancel }) {
|
|
|
5467
5955
|
{ key: "nickname", label: "Enter a Nickname (Agent will use this): " },
|
|
5468
5956
|
{ key: "instructions", label: "System Instructions (Persona overrides): " }
|
|
5469
5957
|
];
|
|
5470
|
-
|
|
5958
|
+
useEffect6(() => {
|
|
5471
5959
|
const currentKey = steps[step].key;
|
|
5472
5960
|
setCurrentInput(profile[currentKey] || "");
|
|
5473
5961
|
}, [step, profile]);
|
|
@@ -5515,19 +6003,19 @@ var init_ProfileForm = __esm({
|
|
|
5515
6003
|
});
|
|
5516
6004
|
|
|
5517
6005
|
// src/components/AskUserModal.jsx
|
|
5518
|
-
import React9, { useState as
|
|
5519
|
-
import { Box as Box8, Text as Text9, useInput as
|
|
6006
|
+
import React9, { useState as useState8 } from "react";
|
|
6007
|
+
import { Box as Box8, Text as Text9, useInput as useInput4 } from "ink";
|
|
5520
6008
|
import TextInput3 from "ink-text-input";
|
|
5521
6009
|
var AskUserModal, AskUserModal_default;
|
|
5522
6010
|
var init_AskUserModal = __esm({
|
|
5523
6011
|
"src/components/AskUserModal.jsx"() {
|
|
5524
6012
|
init_terminal();
|
|
5525
6013
|
AskUserModal = ({ question, options, onResolve }) => {
|
|
5526
|
-
const [isSuggestingElse, setIsSuggestingElse] =
|
|
5527
|
-
const [customInput, setCustomInput] =
|
|
5528
|
-
const [selectedIndex, setSelectedIndex] =
|
|
6014
|
+
const [isSuggestingElse, setIsSuggestingElse] = useState8(false);
|
|
6015
|
+
const [customInput, setCustomInput] = useState8("");
|
|
6016
|
+
const [selectedIndex, setSelectedIndex] = useState8(0);
|
|
5529
6017
|
const allOptions = [...options, { id: "CUSTOM", label: "Suggest something else...", description: "Provide a custom response" }];
|
|
5530
|
-
|
|
6018
|
+
useInput4((input, key) => {
|
|
5531
6019
|
if (isSuggestingElse) return;
|
|
5532
6020
|
if (key.leftArrow || key.upArrow) {
|
|
5533
6021
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
@@ -5757,8 +6245,8 @@ ${projectContextBlock}
|
|
|
5757
6245
|
|
|
5758
6246
|
-- FORMATTING --
|
|
5759
6247
|
- GFM Supported
|
|
5760
|
-
- NO CHAT **AFTER** FIRING TOOLS IN
|
|
5761
|
-
- End
|
|
6248
|
+
- NO CHAT **AFTER** FIRING TOOLS IN CURRENT TURN
|
|
6249
|
+
- Task Complete & Results Verified? End response with summary of changes made and files edited
|
|
5762
6250
|
- Basic LaTeX${mode === "Flux" ? "" : ". Kaomojis"}
|
|
5763
6251
|
=== END SYSTEM PROMPT ===`.trim();
|
|
5764
6252
|
};
|
|
@@ -5996,27 +6484,61 @@ var init_history = __esm({
|
|
|
5996
6484
|
return nextLock;
|
|
5997
6485
|
};
|
|
5998
6486
|
loadHistory = async () => {
|
|
6487
|
+
await fs7.ensureDir(HISTORY_DIR);
|
|
6488
|
+
let history = {};
|
|
5999
6489
|
if (await fs7.pathExists(HISTORY_FILE)) {
|
|
6000
6490
|
try {
|
|
6001
|
-
|
|
6491
|
+
history = readEncryptedJson(HISTORY_FILE, {});
|
|
6002
6492
|
} catch (e) {
|
|
6003
|
-
|
|
6493
|
+
history = {};
|
|
6004
6494
|
}
|
|
6005
6495
|
}
|
|
6006
|
-
|
|
6496
|
+
for (const id in history) {
|
|
6497
|
+
const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
|
|
6498
|
+
Object.defineProperty(history[id], "messages", {
|
|
6499
|
+
get: () => {
|
|
6500
|
+
if (fs7.existsSync(chatFile)) {
|
|
6501
|
+
try {
|
|
6502
|
+
return readEncryptedJson(chatFile, []);
|
|
6503
|
+
} catch (e) {
|
|
6504
|
+
return [];
|
|
6505
|
+
}
|
|
6506
|
+
}
|
|
6507
|
+
return [];
|
|
6508
|
+
},
|
|
6509
|
+
set: (msgs) => {
|
|
6510
|
+
try {
|
|
6511
|
+
writeEncryptedJson(chatFile, msgs);
|
|
6512
|
+
} catch (e) {
|
|
6513
|
+
}
|
|
6514
|
+
},
|
|
6515
|
+
enumerable: false,
|
|
6516
|
+
configurable: true
|
|
6517
|
+
});
|
|
6518
|
+
}
|
|
6519
|
+
return history;
|
|
6007
6520
|
};
|
|
6008
6521
|
saveChat = async (id, name, messages) => {
|
|
6009
6522
|
return withLock(async () => {
|
|
6523
|
+
await fs7.ensureDir(HISTORY_DIR);
|
|
6010
6524
|
const history = await loadHistory();
|
|
6011
6525
|
const existingChat = history[id];
|
|
6012
6526
|
const persistentMessages = (messages || []).filter((m) => !m.isUpdateNotification && !m.isMeta);
|
|
6013
6527
|
const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
|
|
6528
|
+
const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
|
|
6529
|
+
writeEncryptedJson(chatFile, persistentMessages);
|
|
6014
6530
|
history[id] = {
|
|
6015
6531
|
name: finalName,
|
|
6016
|
-
messages: persistentMessages,
|
|
6017
6532
|
updatedAt: Date.now()
|
|
6018
6533
|
};
|
|
6019
|
-
|
|
6534
|
+
const indexHistory = {};
|
|
6535
|
+
for (const chatId in history) {
|
|
6536
|
+
indexHistory[chatId] = {
|
|
6537
|
+
name: history[chatId].name,
|
|
6538
|
+
updatedAt: history[chatId].updatedAt
|
|
6539
|
+
};
|
|
6540
|
+
}
|
|
6541
|
+
writeEncryptedJson(HISTORY_FILE, indexHistory);
|
|
6020
6542
|
});
|
|
6021
6543
|
};
|
|
6022
6544
|
saveChatTitle = async (id, title) => {
|
|
@@ -6026,16 +6548,30 @@ var init_history = __esm({
|
|
|
6026
6548
|
history[id].name = title;
|
|
6027
6549
|
history[id].updatedAt = Date.now();
|
|
6028
6550
|
} else {
|
|
6029
|
-
history[id] = { name: title,
|
|
6551
|
+
history[id] = { name: title, updatedAt: Date.now() };
|
|
6552
|
+
}
|
|
6553
|
+
const indexHistory = {};
|
|
6554
|
+
for (const chatId in history) {
|
|
6555
|
+
indexHistory[chatId] = {
|
|
6556
|
+
name: history[chatId].name,
|
|
6557
|
+
updatedAt: history[chatId].updatedAt
|
|
6558
|
+
};
|
|
6030
6559
|
}
|
|
6031
|
-
writeEncryptedJson(HISTORY_FILE,
|
|
6560
|
+
writeEncryptedJson(HISTORY_FILE, indexHistory);
|
|
6032
6561
|
});
|
|
6033
6562
|
};
|
|
6034
6563
|
deleteChat = async (id) => {
|
|
6035
6564
|
return withLock(async () => {
|
|
6036
6565
|
const history = await loadHistory();
|
|
6037
6566
|
delete history[id];
|
|
6038
|
-
|
|
6567
|
+
const indexHistory = {};
|
|
6568
|
+
for (const chatId in history) {
|
|
6569
|
+
indexHistory[chatId] = {
|
|
6570
|
+
name: history[chatId].name,
|
|
6571
|
+
updatedAt: history[chatId].updatedAt
|
|
6572
|
+
};
|
|
6573
|
+
}
|
|
6574
|
+
writeEncryptedJson(HISTORY_FILE, indexHistory);
|
|
6039
6575
|
if (await fs7.pathExists(CONTEXT_FILE)) {
|
|
6040
6576
|
try {
|
|
6041
6577
|
const contextData = readEncryptedJson(CONTEXT_FILE, []);
|
|
@@ -6057,6 +6593,13 @@ var init_history = __esm({
|
|
|
6057
6593
|
writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
|
|
6058
6594
|
}
|
|
6059
6595
|
await RevertManager.deleteChatBackups(id);
|
|
6596
|
+
const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
|
|
6597
|
+
if (await fs7.pathExists(chatFile)) {
|
|
6598
|
+
try {
|
|
6599
|
+
await fs7.remove(chatFile);
|
|
6600
|
+
} catch (e) {
|
|
6601
|
+
}
|
|
6602
|
+
}
|
|
6060
6603
|
return history;
|
|
6061
6604
|
});
|
|
6062
6605
|
};
|
|
@@ -7759,8 +8302,10 @@ var init_search_keyword = __esm({
|
|
|
7759
8302
|
"src/tools/search_keyword.js"() {
|
|
7760
8303
|
init_arg_parser();
|
|
7761
8304
|
search_keyword = async (args) => {
|
|
7762
|
-
const { keyword, file } = parseArgs(args);
|
|
8305
|
+
const { keyword, file, subString } = parseArgs(args);
|
|
7763
8306
|
if (!keyword) return 'ERROR: Missing "keyword" argument.';
|
|
8307
|
+
const matchSubstring = subString === true || subString === "true" || subString === 1 || subString === "1" || subString === "true";
|
|
8308
|
+
const wordRegex = new RegExp(`(?<![\\w])${keyword.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w])`, "i");
|
|
7764
8309
|
const excludes = [
|
|
7765
8310
|
"node_modules",
|
|
7766
8311
|
".git",
|
|
@@ -7800,7 +8345,8 @@ var init_search_keyword = __esm({
|
|
|
7800
8345
|
const lines = content.split(/\r?\n/);
|
|
7801
8346
|
const fileMatches = [];
|
|
7802
8347
|
for (let i = 0; i < lines.length; i++) {
|
|
7803
|
-
|
|
8348
|
+
const matched = matchSubstring ? lines[i].toLowerCase().includes(keyword.toLowerCase()) : wordRegex.test(lines[i]);
|
|
8349
|
+
if (matched) {
|
|
7804
8350
|
const displayPath = fileObj.relativePath.replace(/\\/g, "/");
|
|
7805
8351
|
fileMatches.push(`${displayPath} \u2192 ${i + 1}`);
|
|
7806
8352
|
}
|
|
@@ -7816,9 +8362,9 @@ var init_search_keyword = __esm({
|
|
|
7816
8362
|
global.gc();
|
|
7817
8363
|
}
|
|
7818
8364
|
if (matches.length === 0) {
|
|
7819
|
-
return `Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ". Try to specify files"}`;
|
|
8365
|
+
return `Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ". Try to specify files"} ${matchSubstring ? "(subString mode)" : ""}`;
|
|
7820
8366
|
}
|
|
7821
|
-
let output = `Found ${matches.length} matches:
|
|
8367
|
+
let output = `Found ${matches.length} matches ${matchSubstring ? "(subString mode)" : ""}:
|
|
7822
8368
|
|
|
7823
8369
|
`;
|
|
7824
8370
|
output += matches.join("\n");
|
|
@@ -8796,7 +9342,7 @@ var init_editor = __esm({
|
|
|
8796
9342
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
8797
9343
|
import path19 from "path";
|
|
8798
9344
|
import fs20 from "fs";
|
|
8799
|
-
var client, globalSettings, colorMainWords, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream;
|
|
9345
|
+
var client, globalSettings, colorMainWords, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream;
|
|
8800
9346
|
var init_ai = __esm({
|
|
8801
9347
|
async "src/utils/ai.js"() {
|
|
8802
9348
|
await init_prompts();
|
|
@@ -8816,7 +9362,7 @@ var init_ai = __esm({
|
|
|
8816
9362
|
colorMainWords = (label2) => {
|
|
8817
9363
|
if (!label2) return label2;
|
|
8818
9364
|
return label2.replace(/(?:(\x1b\[\d+m))?([✔✗✖🔍📖→➕↻•])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
|
|
8819
|
-
return `${ansiBefore || ""}${icon}${ansiAfter || ""}
|
|
9365
|
+
return `${ansiBefore || ""}${icon}${ansiAfter || ""} \x1B[95m${word}\x1B[0m`;
|
|
8820
9366
|
});
|
|
8821
9367
|
};
|
|
8822
9368
|
TERMINATION_SIGNAL = false;
|
|
@@ -8836,13 +9382,11 @@ var init_ai = __esm({
|
|
|
8836
9382
|
"moonshotai/kimi-k2.6",
|
|
8837
9383
|
// NVIDIA vision models
|
|
8838
9384
|
"moonshotai/kimi-k2.6",
|
|
9385
|
+
"stepfun-ai/step-3.7-flash",
|
|
9386
|
+
"google/gemma-4-31b-it",
|
|
9387
|
+
"mistralai/mistral-medium-3.5-128b"
|
|
8839
9388
|
// Google models
|
|
8840
|
-
|
|
8841
|
-
"gemini-2.5-flash",
|
|
8842
|
-
"gemini-3-flash-preview",
|
|
8843
|
-
"gemini-3.5-flash",
|
|
8844
|
-
"gemini-3.1-flash-lite",
|
|
8845
|
-
"gemini-3.1-pro-preview"
|
|
9389
|
+
// No need. All models on Gemini API is Multimodal
|
|
8846
9390
|
];
|
|
8847
9391
|
isModelMultimodal = (model) => {
|
|
8848
9392
|
if (!model) return false;
|
|
@@ -8906,7 +9450,7 @@ var init_ai = __esm({
|
|
|
8906
9450
|
}
|
|
8907
9451
|
return fetch(url, options);
|
|
8908
9452
|
};
|
|
8909
|
-
getDeepSeekStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.
|
|
9453
|
+
getDeepSeekStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.99) {
|
|
8910
9454
|
const messages = [];
|
|
8911
9455
|
if (systemInstruction) {
|
|
8912
9456
|
messages.push({ role: "system", content: systemInstruction });
|
|
@@ -9038,7 +9582,7 @@ var init_ai = __esm({
|
|
|
9038
9582
|
}
|
|
9039
9583
|
}
|
|
9040
9584
|
};
|
|
9041
|
-
getNVIDIAStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal = false, signal, temperature = 0.
|
|
9585
|
+
getNVIDIAStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal = false, signal, temperature = 0.99) {
|
|
9042
9586
|
const messages = [];
|
|
9043
9587
|
if (systemInstruction) {
|
|
9044
9588
|
messages.push({ role: "system", content: systemInstruction });
|
|
@@ -9054,7 +9598,7 @@ var init_ai = __esm({
|
|
|
9054
9598
|
const mimeType = part.inlineData.mimeType;
|
|
9055
9599
|
const data = part.inlineData.data;
|
|
9056
9600
|
const isImage = mimeType.startsWith("image/");
|
|
9057
|
-
if (isImage) {
|
|
9601
|
+
if (isImage && MULTIMODAL_MODELS.includes(model)) {
|
|
9058
9602
|
msgContent.push({
|
|
9059
9603
|
type: "image_url",
|
|
9060
9604
|
image_url: {
|
|
@@ -9078,7 +9622,7 @@ var init_ai = __esm({
|
|
|
9078
9622
|
"High": "High",
|
|
9079
9623
|
"xHigh": "High"
|
|
9080
9624
|
};
|
|
9081
|
-
const apiLevel = thinkingLevelMap[thinkingLevel] || "
|
|
9625
|
+
const apiLevel = thinkingLevelMap[thinkingLevel] || "High";
|
|
9082
9626
|
const isThinking = apiLevel !== "Fast";
|
|
9083
9627
|
const isKimi = model.includes("kimi");
|
|
9084
9628
|
const isGemma = model.includes("gemma");
|
|
@@ -9086,6 +9630,15 @@ var init_ai = __esm({
|
|
|
9086
9630
|
const isGlm = model.includes("glm");
|
|
9087
9631
|
const isMistral = model.includes("mistral");
|
|
9088
9632
|
const isMinimax = model.includes("minimax");
|
|
9633
|
+
const isGPT = model.includes("gpt");
|
|
9634
|
+
const GPT_THINKING_LEVELS = {
|
|
9635
|
+
"Fast": "low",
|
|
9636
|
+
"Low": "low",
|
|
9637
|
+
"Medium": "medium",
|
|
9638
|
+
"Standard": "medium",
|
|
9639
|
+
"High": "high",
|
|
9640
|
+
"xHigh": "high"
|
|
9641
|
+
};
|
|
9089
9642
|
const maxTokens = isMinimax || isDeepSeek ? 16384 : 32768;
|
|
9090
9643
|
const body = {
|
|
9091
9644
|
model,
|
|
@@ -9093,7 +9646,8 @@ var init_ai = __esm({
|
|
|
9093
9646
|
max_tokens: maxTokens,
|
|
9094
9647
|
stream: true,
|
|
9095
9648
|
stream_options: { include_usage: true },
|
|
9096
|
-
temperature
|
|
9649
|
+
temperature,
|
|
9650
|
+
...isGPT && { thinking: GPT_THINKING_LEVELS[thinkingLevel] || "high" }
|
|
9097
9651
|
};
|
|
9098
9652
|
if (isKimi) {
|
|
9099
9653
|
body.chat_template_kwargs = { thinking: isThinking };
|
|
@@ -9190,7 +9744,7 @@ var init_ai = __esm({
|
|
|
9190
9744
|
}
|
|
9191
9745
|
}
|
|
9192
9746
|
};
|
|
9193
|
-
getOpenRouterStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.
|
|
9747
|
+
getOpenRouterStream = async function* (apiKey, model, contents, systemInstruction, thinkingLevel, mode, isMultiModal, signal, temperature = 0.95) {
|
|
9194
9748
|
const messages = [];
|
|
9195
9749
|
if (systemInstruction) {
|
|
9196
9750
|
messages.push({ role: "system", content: systemInstruction });
|
|
@@ -9437,7 +9991,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9437
9991
|
mode,
|
|
9438
9992
|
false,
|
|
9439
9993
|
null,
|
|
9440
|
-
0.
|
|
9994
|
+
0.75
|
|
9441
9995
|
);
|
|
9442
9996
|
const iterator2 = stream[Symbol.asyncIterator]();
|
|
9443
9997
|
const firstResult2 = await iterator2.next();
|
|
@@ -9453,7 +10007,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9453
10007
|
mode,
|
|
9454
10008
|
false,
|
|
9455
10009
|
null,
|
|
9456
|
-
0.
|
|
10010
|
+
0.75
|
|
9457
10011
|
);
|
|
9458
10012
|
const iterator2 = stream[Symbol.asyncIterator]();
|
|
9459
10013
|
const firstResult2 = await iterator2.next();
|
|
@@ -9469,7 +10023,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9469
10023
|
mode,
|
|
9470
10024
|
false,
|
|
9471
10025
|
null,
|
|
9472
|
-
0.
|
|
10026
|
+
0.75
|
|
9473
10027
|
);
|
|
9474
10028
|
const iterator2 = stream[Symbol.asyncIterator]();
|
|
9475
10029
|
const firstResult2 = await iterator2.next();
|
|
@@ -9481,7 +10035,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9481
10035
|
config: {
|
|
9482
10036
|
systemInstruction: janitorPrompt,
|
|
9483
10037
|
maxOutputTokens: 512,
|
|
9484
|
-
temperature: 0.
|
|
10038
|
+
temperature: 0.75,
|
|
9485
10039
|
safetySettings: [
|
|
9486
10040
|
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
9487
10041
|
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
@@ -9778,9 +10332,69 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9778
10332
|
getSanitizedText = (text) => {
|
|
9779
10333
|
return getContextSafeText(text, true);
|
|
9780
10334
|
};
|
|
10335
|
+
translateKimiToolCalls = (text) => {
|
|
10336
|
+
if (!text) return text;
|
|
10337
|
+
const PASCAL_MAP = {
|
|
10338
|
+
"patchfile": "PatchFile",
|
|
10339
|
+
"writefile": "WriteFile",
|
|
10340
|
+
"readfile": "ReadFile",
|
|
10341
|
+
"viewfile": "ReadFile",
|
|
10342
|
+
"run": "Run",
|
|
10343
|
+
"execcommand": "Run",
|
|
10344
|
+
"searchkeyword": "SearchKeyword",
|
|
10345
|
+
"websearch": "WebSearch",
|
|
10346
|
+
"webscrape": "WebScrape",
|
|
10347
|
+
"readfolder": "ReadFolder",
|
|
10348
|
+
"writepdf": "WritePDF",
|
|
10349
|
+
"writedoc": "WriteDoc",
|
|
10350
|
+
"writedocx": "WriteDoc",
|
|
10351
|
+
"filemap": "FileMap",
|
|
10352
|
+
"generateimage": "GenerateImage",
|
|
10353
|
+
"todo": "Todo",
|
|
10354
|
+
"ask": "Ask"
|
|
10355
|
+
};
|
|
10356
|
+
const toPascalCase = (str) => {
|
|
10357
|
+
return str.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join("");
|
|
10358
|
+
};
|
|
10359
|
+
const kimiRegex = /<\|\s*tool_call_begin\s*\|>\s*(?:(?:tool|functions)\b[\s._]*)*([a-zA-Z0-9_]+)(?::\d+)?\s*<\|\s*tool_call_argument_begin\s*\|>([\s\S]*?)<\|\s*tool_call_end\s*\|>/gi;
|
|
10360
|
+
let result = text.replace(kimiRegex, (match, toolName, argsJsonStr) => {
|
|
10361
|
+
let parsedArgs = "";
|
|
10362
|
+
try {
|
|
10363
|
+
const argsObj = JSON.parse(argsJsonStr.trim());
|
|
10364
|
+
if (argsObj && typeof argsObj === "object") {
|
|
10365
|
+
const argPairs = Object.entries(argsObj).map(([key, val]) => {
|
|
10366
|
+
const stringVal = typeof val === "string" ? val : JSON.stringify(val);
|
|
10367
|
+
return `${key}=${JSON.stringify(stringVal)}`;
|
|
10368
|
+
});
|
|
10369
|
+
parsedArgs = argPairs.join(", ");
|
|
10370
|
+
}
|
|
10371
|
+
} catch (e) {
|
|
10372
|
+
const pairs = [];
|
|
10373
|
+
const pairRegex = /"([^"]+)"\s*:\s*(?:"([^"]*)"|(\d+)|true|false|null)/g;
|
|
10374
|
+
let pMatch;
|
|
10375
|
+
while ((pMatch = pairRegex.exec(argsJsonStr)) !== null) {
|
|
10376
|
+
const key = pMatch[1];
|
|
10377
|
+
const val = pMatch[2] !== void 0 ? pMatch[2] : pMatch[0].split(":").slice(1).join(":").trim();
|
|
10378
|
+
pairs.push(`${key}=${JSON.stringify(val)}`);
|
|
10379
|
+
}
|
|
10380
|
+
if (pairs.length > 0) {
|
|
10381
|
+
parsedArgs = pairs.join(", ");
|
|
10382
|
+
} else {
|
|
10383
|
+
parsedArgs = argsJsonStr.trim();
|
|
10384
|
+
}
|
|
10385
|
+
}
|
|
10386
|
+
const cleanKey = toolName.toLowerCase().replace(/_/g, "");
|
|
10387
|
+
const normToolName = PASCAL_MAP[cleanKey] || toPascalCase(toolName);
|
|
10388
|
+
return `[tool:functions.${normToolName}(${parsedArgs})]`;
|
|
10389
|
+
});
|
|
10390
|
+
result = result.replace(/<\|\s*tool_calls_section_begin\s*\|>/gi, "");
|
|
10391
|
+
result = result.replace(/<\|\s*tool_calls_section_end\s*\|>/gi, "");
|
|
10392
|
+
return result;
|
|
10393
|
+
};
|
|
9781
10394
|
detectToolCalls = (text) => {
|
|
9782
10395
|
if (!text) return [];
|
|
9783
|
-
const
|
|
10396
|
+
const translatedText = translateKimiToolCalls(text);
|
|
10397
|
+
const cleanText = translatedText.replace(/(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi, "");
|
|
9784
10398
|
const results = [];
|
|
9785
10399
|
const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
|
|
9786
10400
|
let match;
|
|
@@ -9841,7 +10455,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9841
10455
|
client = new GoogleGenAI({ apiKey });
|
|
9842
10456
|
return client;
|
|
9843
10457
|
};
|
|
9844
|
-
generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.
|
|
10458
|
+
generateSimpleContent = async (settings, model, contents, systemInstruction, thinkingLevel = "Fast", temperature = 0.75) => {
|
|
9845
10459
|
const { aiProvider = "Google", apiKey, mode } = settings;
|
|
9846
10460
|
let fullText = "";
|
|
9847
10461
|
let usageMetadata = null;
|
|
@@ -9859,7 +10473,6 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
|
|
|
9859
10473
|
contents: normalizedContents,
|
|
9860
10474
|
config: {
|
|
9861
10475
|
systemInstruction,
|
|
9862
|
-
maxOutputTokens: 2048,
|
|
9863
10476
|
temperature,
|
|
9864
10477
|
thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
|
|
9865
10478
|
}
|
|
@@ -10695,7 +11308,9 @@ ${boxMid}`) };
|
|
|
10695
11308
|
if (taggedContextBlocks.length > 0) {
|
|
10696
11309
|
taggedContextStr = "[TAGGED CONTEXT]\n" + taggedContextBlocks.join("\n\n") + "\n[/TAGGED CONTEXT]\n";
|
|
10697
11310
|
}
|
|
11311
|
+
const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
|
|
10698
11312
|
const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr}
|
|
11313
|
+
OS: ${osDetected}
|
|
10699
11314
|
CWD: ${process.cwd()}${isPlayground ? " [PLAYGROUND MODE]" : ""}${cwdMismatch ? ` (WARNING: CWD Mismatch! Previous Path: ${lastCwd})` : ""}
|
|
10700
11315
|
**DIRECTORY STRUCTURE**
|
|
10701
11316
|
${dirStructure}${memoryPrompt}${ideBlock}
|
|
@@ -10774,6 +11389,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
|
|
|
10774
11389
|
let isStutteringLoop = false;
|
|
10775
11390
|
let isGeneralLoop = false;
|
|
10776
11391
|
let isInitialAttempt = true;
|
|
11392
|
+
let lastLoopCheckLen = 0;
|
|
10777
11393
|
let accumulatedContext = "";
|
|
10778
11394
|
let dedupeBuffer = "";
|
|
10779
11395
|
let isDedupeActive = false;
|
|
@@ -10878,7 +11494,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
|
|
|
10878
11494
|
} else if (retryCount > 0) {
|
|
10879
11495
|
yield { type: "model_update", content: null };
|
|
10880
11496
|
}
|
|
10881
|
-
currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? "GEM" : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt, aiProvider, isMultiModal);
|
|
11497
|
+
currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? "GEM" : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt, aiProvider, aiProvider === "Google" ? true : isMultiModal);
|
|
10882
11498
|
const lastUserMsg = contents[contents.length - 1];
|
|
10883
11499
|
if (isBridgeConnected() & loop > 0) {
|
|
10884
11500
|
yield { type: "status", content: "Checking Code..." };
|
|
@@ -10926,7 +11542,7 @@ ${ideErr} [/ERROR]`;
|
|
|
10926
11542
|
mode,
|
|
10927
11543
|
isMultiModal,
|
|
10928
11544
|
abortController.signal,
|
|
10929
|
-
0.
|
|
11545
|
+
0.95
|
|
10930
11546
|
);
|
|
10931
11547
|
} else if (aiProvider === "DeepSeek") {
|
|
10932
11548
|
stream = getDeepSeekStream(
|
|
@@ -10938,7 +11554,7 @@ ${ideErr} [/ERROR]`;
|
|
|
10938
11554
|
mode,
|
|
10939
11555
|
isMultiModal,
|
|
10940
11556
|
abortController.signal,
|
|
10941
|
-
0.
|
|
11557
|
+
0.99
|
|
10942
11558
|
);
|
|
10943
11559
|
} else if (aiProvider === "NVIDIA") {
|
|
10944
11560
|
stream = getNVIDIAStream(
|
|
@@ -10950,7 +11566,7 @@ ${ideErr} [/ERROR]`;
|
|
|
10950
11566
|
mode,
|
|
10951
11567
|
isMultiModal,
|
|
10952
11568
|
abortController.signal,
|
|
10953
|
-
0.
|
|
11569
|
+
0.99
|
|
10954
11570
|
);
|
|
10955
11571
|
} else {
|
|
10956
11572
|
const apiCallPromise = client.models.generateContentStream({
|
|
@@ -10959,7 +11575,7 @@ ${ideErr} [/ERROR]`;
|
|
|
10959
11575
|
config: {
|
|
10960
11576
|
systemInstruction: currentSystemInstruction,
|
|
10961
11577
|
mediaResolution: "MEDIA_RESOLUTION_MEDIUM",
|
|
10962
|
-
temperature: 1
|
|
11578
|
+
temperature: 1,
|
|
10963
11579
|
safetySettings: [
|
|
10964
11580
|
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
10965
11581
|
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
@@ -11037,9 +11653,13 @@ ${ideErr} [/ERROR]`;
|
|
|
11037
11653
|
if (!isBufferingToolCall) {
|
|
11038
11654
|
const toolIdx = remaining.indexOf("[tool");
|
|
11039
11655
|
const endIdx = remaining.indexOf("[[END]]");
|
|
11656
|
+
const kimiSectionIdx = remaining.indexOf("<|tool_calls_section_begin|>");
|
|
11657
|
+
const kimiCallIdx = remaining.indexOf("<|tool_call_begin|>");
|
|
11040
11658
|
const indices = [
|
|
11041
11659
|
{ type: "tool", idx: toolIdx, start: "[tool", end: "]" },
|
|
11042
|
-
{ type: "end", idx: endIdx, start: "[[END]]", end: "[[END]]" }
|
|
11660
|
+
{ type: "end", idx: endIdx, start: "[[END]]", end: "[[END]]" },
|
|
11661
|
+
{ type: "kimi_section", idx: kimiSectionIdx, start: "<|tool_calls_section_begin|>", end: "<|tool_calls_section_end|>" },
|
|
11662
|
+
{ type: "kimi_call", idx: kimiCallIdx, start: "<|tool_call_begin|>", end: "<|tool_call_end|>" }
|
|
11043
11663
|
].filter((i) => i.idx !== -1).sort((a, b) => a.idx - b.idx);
|
|
11044
11664
|
if (indices.length > 0) {
|
|
11045
11665
|
const match2 = indices[0];
|
|
@@ -11051,13 +11671,17 @@ ${ideErr} [/ERROR]`;
|
|
|
11051
11671
|
toolCallBuffer = "";
|
|
11052
11672
|
remaining = remaining.substring(match2.idx);
|
|
11053
11673
|
} else {
|
|
11054
|
-
const potentialStarts = ["[tool", "[[END]]"];
|
|
11674
|
+
const potentialStarts = ["[tool", "[[END]]", "<|tool_calls_section_begin|>", "<|tool_call_begin|>"];
|
|
11055
11675
|
let splitPoint = -1;
|
|
11056
11676
|
for (const start of potentialStarts) {
|
|
11057
11677
|
for (let len = start.length - 1; len > 0; len--) {
|
|
11058
11678
|
if (remaining.endsWith(start.substring(0, len))) {
|
|
11059
11679
|
splitPoint = remaining.length - len;
|
|
11060
|
-
|
|
11680
|
+
const idx = potentialStarts.indexOf(start);
|
|
11681
|
+
if (idx === 0) activeBufferType = "tool";
|
|
11682
|
+
else if (idx === 1) activeBufferType = "end";
|
|
11683
|
+
else if (idx === 2) activeBufferType = "kimi_section";
|
|
11684
|
+
else activeBufferType = "kimi_call";
|
|
11061
11685
|
break;
|
|
11062
11686
|
}
|
|
11063
11687
|
}
|
|
@@ -11076,7 +11700,6 @@ ${ideErr} [/ERROR]`;
|
|
|
11076
11700
|
}
|
|
11077
11701
|
}
|
|
11078
11702
|
} else {
|
|
11079
|
-
const endTag = activeBufferType === "tool" ? "]" : "[[END]]";
|
|
11080
11703
|
const combined = toolCallBuffer + remaining;
|
|
11081
11704
|
if (activeBufferType === "tool") {
|
|
11082
11705
|
const protocolPrefix = "[tool:functions.";
|
|
@@ -11090,6 +11713,7 @@ ${ideErr} [/ERROR]`;
|
|
|
11090
11713
|
}
|
|
11091
11714
|
}
|
|
11092
11715
|
let endIdx = -1;
|
|
11716
|
+
let endTag = "]";
|
|
11093
11717
|
if (activeBufferType === "tool") {
|
|
11094
11718
|
let balance = 0;
|
|
11095
11719
|
let inString = null;
|
|
@@ -11127,19 +11751,27 @@ ${ideErr} [/ERROR]`;
|
|
|
11127
11751
|
}
|
|
11128
11752
|
}
|
|
11129
11753
|
} else {
|
|
11754
|
+
if (activeBufferType === "end") endTag = "[[END]]";
|
|
11755
|
+
else if (activeBufferType === "kimi_section") endTag = "<|tool_calls_section_end|>";
|
|
11756
|
+
else if (activeBufferType === "kimi_call") endTag = "<|tool_call_end|>";
|
|
11130
11757
|
endIdx = combined.indexOf(endTag);
|
|
11131
11758
|
}
|
|
11132
11759
|
if (endIdx !== -1) {
|
|
11133
|
-
const
|
|
11134
|
-
|
|
11760
|
+
const endLen = endTag.length;
|
|
11761
|
+
if (!activeBufferType.startsWith("kimi")) {
|
|
11762
|
+
const fullMatch = combined.substring(0, endIdx + endLen);
|
|
11763
|
+
msgs.push({ type: "text", content: fullMatch });
|
|
11764
|
+
}
|
|
11135
11765
|
toolCallBuffer = "";
|
|
11136
11766
|
isBufferingToolCall = false;
|
|
11137
11767
|
activeBufferType = null;
|
|
11138
|
-
remaining = combined.substring(endIdx +
|
|
11768
|
+
remaining = combined.substring(endIdx + endLen);
|
|
11139
11769
|
} else {
|
|
11140
|
-
const MAX_BUFFER = 512;
|
|
11770
|
+
const MAX_BUFFER = activeBufferType.startsWith("kimi") ? 8192 : 512;
|
|
11141
11771
|
if (combined.length > MAX_BUFFER) {
|
|
11142
|
-
|
|
11772
|
+
if (!activeBufferType.startsWith("kimi")) {
|
|
11773
|
+
msgs.push({ type: "text", content: combined });
|
|
11774
|
+
}
|
|
11143
11775
|
toolCallBuffer = "";
|
|
11144
11776
|
isBufferingToolCall = false;
|
|
11145
11777
|
} else {
|
|
@@ -11237,7 +11869,6 @@ ${ideErr} [/ERROR]`;
|
|
|
11237
11869
|
for (const m of msgs) yield m;
|
|
11238
11870
|
}
|
|
11239
11871
|
}
|
|
11240
|
-
const signalSafeText3 = getSanitizedText(turnText);
|
|
11241
11872
|
const toolContext = getActiveToolContext(turnText);
|
|
11242
11873
|
if (toolContext.inside) {
|
|
11243
11874
|
if (!lastToolEventTime) lastToolEventTime = Date.now();
|
|
@@ -11308,78 +11939,60 @@ ${ideErr} [/ERROR]`;
|
|
|
11308
11939
|
}
|
|
11309
11940
|
}
|
|
11310
11941
|
}
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11325
|
-
|
|
11326
|
-
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
const reason = repetitionRatio > repetitionThresholdThinking ? "Reasoning Loop Detected" : "Thinking Budget Exceeded";
|
|
11334
|
-
yield { type: "status", content: `${reason}. Re-centering...` };
|
|
11335
|
-
isThinkingLoop = true;
|
|
11336
|
-
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
11337
|
-
break;
|
|
11338
|
-
}
|
|
11339
|
-
const responseContent = signalSafeText3.trim();
|
|
11340
|
-
const respSentences = responseContent.split(/[.!?]\s+/);
|
|
11341
|
-
const uniqueRespSentences = new Set(respSentences);
|
|
11342
|
-
const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
|
|
11343
|
-
if (respRepetitionRatio > repetitionThresholdResponse) {
|
|
11344
|
-
yield { type: "status", content: `Response Loop Detected. Re-centering...` };
|
|
11345
|
-
isThinkingLoop = false;
|
|
11346
|
-
isGeneralLoop = true;
|
|
11347
|
-
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
11348
|
-
break;
|
|
11349
|
-
}
|
|
11350
|
-
const allWords = contextSafeText.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
|
|
11351
|
-
let stutterDetected = false;
|
|
11352
|
-
if (allWords.length > 5) {
|
|
11353
|
-
for (let p = 1; p <= 15; p++) {
|
|
11354
|
-
const R = Math.max(3, Math.ceil(8 / p));
|
|
11355
|
-
if (allWords.length < p * R) continue;
|
|
11356
|
-
let isRepeating = true;
|
|
11357
|
-
const pattern = allWords.slice(allWords.length - p);
|
|
11358
|
-
const patternStr = pattern.join(" ");
|
|
11359
|
-
for (let r = 1; r < R; r++) {
|
|
11360
|
-
const prevPattern = allWords.slice(allWords.length - p * (r + 1), allWords.length - p * r);
|
|
11361
|
-
if (prevPattern.join(" ") !== patternStr) {
|
|
11362
|
-
isRepeating = false;
|
|
11363
|
-
break;
|
|
11364
|
-
}
|
|
11365
|
-
}
|
|
11366
|
-
if (isRepeating) {
|
|
11367
|
-
stutterDetected = true;
|
|
11368
|
-
break;
|
|
11369
|
-
}
|
|
11942
|
+
if (turnText.length - lastLoopCheckLen > 150) {
|
|
11943
|
+
lastLoopCheckLen = turnText.length;
|
|
11944
|
+
const contextSafeText = getContextSafeText(turnText, false);
|
|
11945
|
+
const thinkBlocks = contextSafeText.match(/(?:<think>|\[think\])([\s\S]*?)(?:<\/think>|\[\/think\]|$)/gi) || [];
|
|
11946
|
+
const thinkContent = thinkBlocks.join("").trim();
|
|
11947
|
+
const sentences = thinkContent.split(/[.!?]\s+/);
|
|
11948
|
+
const uniqueSentences = new Set(sentences);
|
|
11949
|
+
const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
|
|
11950
|
+
const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
|
|
11951
|
+
let repetitionThresholdThinking = 0.4;
|
|
11952
|
+
let repetitionThresholdResponse = 0.6;
|
|
11953
|
+
let isOverVerboseThinking = false;
|
|
11954
|
+
if ((targetModel || "").toLowerCase().startsWith("gemma")) {
|
|
11955
|
+
const thinkingCaps = {
|
|
11956
|
+
"low": 256,
|
|
11957
|
+
"medium": 768,
|
|
11958
|
+
"high": 2048,
|
|
11959
|
+
"max": 4096,
|
|
11960
|
+
"xhigh": 4096
|
|
11961
|
+
};
|
|
11962
|
+
const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
|
|
11963
|
+
isOverVerboseThinking = wordCount > cap;
|
|
11370
11964
|
}
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11965
|
+
if (repetitionRatio > repetitionThresholdThinking || isOverVerboseThinking) {
|
|
11966
|
+
const reason = repetitionRatio > repetitionThresholdThinking ? "Reasoning Loop Detected" : "Thinking Budget Exceeded";
|
|
11967
|
+
yield { type: "status", content: `${reason}. Re-centering...` };
|
|
11968
|
+
isThinkingLoop = true;
|
|
11969
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
11970
|
+
break;
|
|
11971
|
+
}
|
|
11972
|
+
const signalSafeText3 = getSanitizedText(turnText);
|
|
11973
|
+
const responseContent = signalSafeText3.trim();
|
|
11974
|
+
const respSentences = responseContent.split(/[.!?]\s+/);
|
|
11975
|
+
const uniqueRespSentences = new Set(respSentences);
|
|
11976
|
+
const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
|
|
11977
|
+
if (respRepetitionRatio > repetitionThresholdResponse) {
|
|
11978
|
+
yield { type: "status", content: `Response Loop Detected. Re-centering...` };
|
|
11979
|
+
isThinkingLoop = false;
|
|
11980
|
+
isGeneralLoop = true;
|
|
11981
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
11982
|
+
break;
|
|
11983
|
+
}
|
|
11984
|
+
const allWords = contextSafeText.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
|
|
11985
|
+
let stutterDetected = false;
|
|
11986
|
+
if (allWords.length > 5) {
|
|
11987
|
+
for (let p = 1; p <= 15; p++) {
|
|
11988
|
+
const R = Math.max(3, Math.ceil(8 / p));
|
|
11989
|
+
if (allWords.length < p * R) continue;
|
|
11379
11990
|
let isRepeating = true;
|
|
11991
|
+
const pattern = allWords.slice(allWords.length - p);
|
|
11992
|
+
const patternStr = pattern.join(" ");
|
|
11380
11993
|
for (let r = 1; r < R; r++) {
|
|
11381
|
-
const prevPattern =
|
|
11382
|
-
if (prevPattern !==
|
|
11994
|
+
const prevPattern = allWords.slice(allWords.length - p * (r + 1), allWords.length - p * r);
|
|
11995
|
+
if (prevPattern.join(" ") !== patternStr) {
|
|
11383
11996
|
isRepeating = false;
|
|
11384
11997
|
break;
|
|
11385
11998
|
}
|
|
@@ -11390,13 +12003,35 @@ ${ideErr} [/ERROR]`;
|
|
|
11390
12003
|
}
|
|
11391
12004
|
}
|
|
11392
12005
|
}
|
|
11393
|
-
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
|
|
11397
|
-
|
|
11398
|
-
|
|
11399
|
-
|
|
12006
|
+
if (!stutterDetected) {
|
|
12007
|
+
const cleanChars = contextSafeText.toLowerCase().replace(/[^a-z0-9]/gi, "");
|
|
12008
|
+
if (cleanChars.length >= 10) {
|
|
12009
|
+
for (let p = 1; p <= 10; p++) {
|
|
12010
|
+
const R = Math.max(4, Math.ceil(12 / p));
|
|
12011
|
+
if (cleanChars.length < p * R) continue;
|
|
12012
|
+
const pattern = cleanChars.substring(cleanChars.length - p);
|
|
12013
|
+
let isRepeating = true;
|
|
12014
|
+
for (let r = 1; r < R; r++) {
|
|
12015
|
+
const prevPattern = cleanChars.substring(cleanChars.length - p * (r + 1), cleanChars.length - p * r);
|
|
12016
|
+
if (prevPattern !== pattern) {
|
|
12017
|
+
isRepeating = false;
|
|
12018
|
+
break;
|
|
12019
|
+
}
|
|
12020
|
+
}
|
|
12021
|
+
if (isRepeating) {
|
|
12022
|
+
stutterDetected = true;
|
|
12023
|
+
break;
|
|
12024
|
+
}
|
|
12025
|
+
}
|
|
12026
|
+
}
|
|
12027
|
+
}
|
|
12028
|
+
if (stutterDetected) {
|
|
12029
|
+
yield { type: "status", content: `Stuttering Detected. Re-centering...` };
|
|
12030
|
+
isThinkingLoop = false;
|
|
12031
|
+
isStutteringLoop = true;
|
|
12032
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
12033
|
+
break;
|
|
12034
|
+
}
|
|
11400
12035
|
}
|
|
11401
12036
|
const toolActionableText = turnText.replace(/(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi, "");
|
|
11402
12037
|
const allToolsFound = detectToolCalls(toolActionableText);
|
|
@@ -12548,13 +13183,13 @@ Error Log can be found in ${path19.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
12548
13183
|
});
|
|
12549
13184
|
|
|
12550
13185
|
// src/components/ResumeModal.jsx
|
|
12551
|
-
import React10, { useState as
|
|
12552
|
-
import { Box as Box9, Text as Text10, useInput as
|
|
13186
|
+
import React10, { useState as useState9, useEffect as useEffect7 } from "react";
|
|
13187
|
+
import { Box as Box9, Text as Text10, useInput as useInput5 } from "ink";
|
|
12553
13188
|
function ResumeModal({ onSelect, onDelete, onClose }) {
|
|
12554
|
-
const [history, setHistory] =
|
|
12555
|
-
const [keys, setKeys] =
|
|
12556
|
-
const [selectedIndex, setSelectedIndex] =
|
|
12557
|
-
|
|
13189
|
+
const [history, setHistory] = useState9({});
|
|
13190
|
+
const [keys, setKeys] = useState9([]);
|
|
13191
|
+
const [selectedIndex, setSelectedIndex] = useState9(0);
|
|
13192
|
+
useEffect7(() => {
|
|
12558
13193
|
const fetchHistory = async () => {
|
|
12559
13194
|
const h = await loadHistory();
|
|
12560
13195
|
setHistory(h);
|
|
@@ -12562,7 +13197,7 @@ function ResumeModal({ onSelect, onDelete, onClose }) {
|
|
|
12562
13197
|
};
|
|
12563
13198
|
fetchHistory();
|
|
12564
13199
|
}, []);
|
|
12565
|
-
|
|
13200
|
+
useInput5((input, key) => {
|
|
12566
13201
|
if (key.escape) onClose();
|
|
12567
13202
|
if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
12568
13203
|
if (key.downArrow) setSelectedIndex((prev) => Math.min(keys.length - 1, prev + 1));
|
|
@@ -12640,14 +13275,14 @@ var init_ResumeModal = __esm({
|
|
|
12640
13275
|
});
|
|
12641
13276
|
|
|
12642
13277
|
// src/components/MemoryModal.jsx
|
|
12643
|
-
import React11, { useState as
|
|
12644
|
-
import { Box as Box10, Text as Text11, useInput as
|
|
13278
|
+
import React11, { useState as useState10, useEffect as useEffect8 } from "react";
|
|
13279
|
+
import { Box as Box10, Text as Text11, useInput as useInput6, useStdout } from "ink";
|
|
12645
13280
|
function MemoryModal({ onClose }) {
|
|
12646
13281
|
const { stdout } = useStdout();
|
|
12647
13282
|
const columns = stdout?.columns || 80;
|
|
12648
|
-
const [memories, setMemories] =
|
|
12649
|
-
const [selectedIndex, setSelectedIndex] =
|
|
12650
|
-
const [isMemoryOn, setIsMemoryOn] =
|
|
13283
|
+
const [memories, setMemories] = useState10([]);
|
|
13284
|
+
const [selectedIndex, setSelectedIndex] = useState10(0);
|
|
13285
|
+
const [isMemoryOn, setIsMemoryOn] = useState10(true);
|
|
12651
13286
|
const loadMemories = () => {
|
|
12652
13287
|
const data = readEncryptedJson(MEMORIES_FILE, []);
|
|
12653
13288
|
setMemories(data);
|
|
@@ -12659,10 +13294,10 @@ function MemoryModal({ onClose }) {
|
|
|
12659
13294
|
setIsMemoryOn(true);
|
|
12660
13295
|
}
|
|
12661
13296
|
};
|
|
12662
|
-
|
|
13297
|
+
useEffect8(() => {
|
|
12663
13298
|
loadMemories();
|
|
12664
13299
|
}, []);
|
|
12665
|
-
|
|
13300
|
+
useInput6((input, key) => {
|
|
12666
13301
|
if (key.escape) onClose();
|
|
12667
13302
|
if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
12668
13303
|
if (key.downArrow) setSelectedIndex((prev) => Math.min(memories.length - 1, prev + 1));
|
|
@@ -12761,7 +13396,7 @@ var init_MemoryModal = __esm({
|
|
|
12761
13396
|
});
|
|
12762
13397
|
|
|
12763
13398
|
// src/components/UpdateProcessor.jsx
|
|
12764
|
-
import React12, { useState as
|
|
13399
|
+
import React12, { useState as useState11, useEffect as useEffect9 } from "react";
|
|
12765
13400
|
import { Box as Box11, Text as Text12 } from "ink";
|
|
12766
13401
|
import { spawn as spawn2 } from "child_process";
|
|
12767
13402
|
var pty2, SPINNER_FRAMES, UpdateProcessor, UpdateProcessor_default;
|
|
@@ -12776,17 +13411,17 @@ var init_UpdateProcessor = __esm({
|
|
|
12776
13411
|
}
|
|
12777
13412
|
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
12778
13413
|
UpdateProcessor = ({ latest, current, settings, onClose, onUpdateSettings, onSuccess }) => {
|
|
12779
|
-
const [status, setStatus] =
|
|
12780
|
-
const [log, setLog] =
|
|
12781
|
-
const [error, setError] =
|
|
12782
|
-
const [tick, setTick] =
|
|
12783
|
-
|
|
13414
|
+
const [status, setStatus] = useState11("initializing");
|
|
13415
|
+
const [log, setLog] = useState11("");
|
|
13416
|
+
const [error, setError] = useState11(null);
|
|
13417
|
+
const [tick, setTick] = useState11(0);
|
|
13418
|
+
useEffect9(() => {
|
|
12784
13419
|
const interval = setInterval(() => {
|
|
12785
13420
|
setTick((t) => (t + 1) % 1e3);
|
|
12786
13421
|
}, 33);
|
|
12787
13422
|
return () => clearInterval(interval);
|
|
12788
13423
|
}, []);
|
|
12789
|
-
|
|
13424
|
+
useEffect9(() => {
|
|
12790
13425
|
let child;
|
|
12791
13426
|
const runUpdate = async () => {
|
|
12792
13427
|
const manager = settings.updateManager || "npm";
|
|
@@ -12919,12 +13554,12 @@ var init_UpdateProcessor = __esm({
|
|
|
12919
13554
|
});
|
|
12920
13555
|
|
|
12921
13556
|
// src/components/ParserDownloadModal.jsx
|
|
12922
|
-
import React13, { useState as
|
|
12923
|
-
import { Box as Box12, Text as Text13, useInput as
|
|
13557
|
+
import React13, { useState as useState12, useEffect as useEffect10 } from "react";
|
|
13558
|
+
import { Box as Box12, Text as Text13, useInput as useInput7 } from "ink";
|
|
12924
13559
|
function ParserDownloadModal({ onClose }) {
|
|
12925
|
-
const [selectedIndex, setSelectedIndex] =
|
|
12926
|
-
const [status, setStatus] =
|
|
12927
|
-
|
|
13560
|
+
const [selectedIndex, setSelectedIndex] = useState12(0);
|
|
13561
|
+
const [status, setStatus] = useState12({});
|
|
13562
|
+
useEffect10(() => {
|
|
12928
13563
|
const initialStatus = {};
|
|
12929
13564
|
EXTENSIONS.forEach((item) => {
|
|
12930
13565
|
if (isParserInstalled(item.file)) {
|
|
@@ -12935,7 +13570,7 @@ function ParserDownloadModal({ onClose }) {
|
|
|
12935
13570
|
});
|
|
12936
13571
|
setStatus(initialStatus);
|
|
12937
13572
|
}, []);
|
|
12938
|
-
|
|
13573
|
+
useInput7(async (input, key) => {
|
|
12939
13574
|
if (key.escape) onClose();
|
|
12940
13575
|
if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
12941
13576
|
if (key.downArrow) setSelectedIndex((prev) => Math.min(EXTENSIONS.length - 1, prev + 1));
|
|
@@ -13425,11 +14060,11 @@ var init_dist = __esm({
|
|
|
13425
14060
|
});
|
|
13426
14061
|
|
|
13427
14062
|
// src/components/RevertModal.jsx
|
|
13428
|
-
import React14, { useState as
|
|
13429
|
-
import { Box as Box14, Text as Text15, useInput as
|
|
14063
|
+
import React14, { useState as useState13 } from "react";
|
|
14064
|
+
import { Box as Box14, Text as Text15, useInput as useInput8 } from "ink";
|
|
13430
14065
|
function RevertModal({ prompts, onSelect, onClose }) {
|
|
13431
|
-
const [selectedIndex, setSelectedIndex] =
|
|
13432
|
-
|
|
14066
|
+
const [selectedIndex, setSelectedIndex] = useState13(0);
|
|
14067
|
+
useInput8((input, key) => {
|
|
13433
14068
|
if (key.escape) onClose();
|
|
13434
14069
|
if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
13435
14070
|
if (key.downArrow) setSelectedIndex((prev) => Math.min(prompts.length - 1, prev + 1));
|
|
@@ -13551,8 +14186,8 @@ __export(app_exports, {
|
|
|
13551
14186
|
default: () => App
|
|
13552
14187
|
});
|
|
13553
14188
|
import os4 from "os";
|
|
13554
|
-
import React15, { useState as
|
|
13555
|
-
import { Box as Box15, Text as Text16, useInput as
|
|
14189
|
+
import React15, { useState as useState14, useEffect as useEffect11, useRef as useRef3, useMemo as useMemo2 } from "react";
|
|
14190
|
+
import { Box as Box15, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
|
|
13556
14191
|
import fs22 from "fs-extra";
|
|
13557
14192
|
import path20 from "path";
|
|
13558
14193
|
import { exec as exec2 } from "child_process";
|
|
@@ -13561,24 +14196,24 @@ import TextInput4 from "ink-text-input";
|
|
|
13561
14196
|
import SelectInput2 from "ink-select-input";
|
|
13562
14197
|
import gradient2 from "gradient-string";
|
|
13563
14198
|
function App({ args = [] }) {
|
|
13564
|
-
const [confirmExit, setConfirmExit] =
|
|
13565
|
-
const [exitCountdown, setExitCountdown] =
|
|
14199
|
+
const [confirmExit, setConfirmExit] = useState14(false);
|
|
14200
|
+
const [exitCountdown, setExitCountdown] = useState14(10);
|
|
13566
14201
|
const { stdout } = useStdout2();
|
|
13567
|
-
const [input, setInput] =
|
|
13568
|
-
const [inputKey, setInputKey] =
|
|
13569
|
-
const [isExpanded, setIsExpanded] =
|
|
13570
|
-
const [mode, setMode] =
|
|
13571
|
-
const [terminalSize, setTerminalSize] =
|
|
14202
|
+
const [input, setInput] = useState14("");
|
|
14203
|
+
const [inputKey, setInputKey] = useState14(0);
|
|
14204
|
+
const [isExpanded, setIsExpanded] = useState14(false);
|
|
14205
|
+
const [mode, setMode] = useState14("Flux");
|
|
14206
|
+
const [terminalSize, setTerminalSize] = useState14({
|
|
13572
14207
|
columns: stdout?.columns || 80,
|
|
13573
14208
|
rows: stdout?.rows || 24
|
|
13574
14209
|
});
|
|
13575
|
-
const [selectedIndex, setSelectedIndex] =
|
|
13576
|
-
const [isFilePickerDismissed, setIsFilePickerDismissed] =
|
|
13577
|
-
const [showBridgePromo, setShowBridgePromo] =
|
|
13578
|
-
const [promoSelectedIndex, setPromoSelectedIndex] =
|
|
14210
|
+
const [selectedIndex, setSelectedIndex] = useState14(0);
|
|
14211
|
+
const [isFilePickerDismissed, setIsFilePickerDismissed] = useState14(false);
|
|
14212
|
+
const [showBridgePromo, setShowBridgePromo] = useState14(false);
|
|
14213
|
+
const [promoSelectedIndex, setPromoSelectedIndex] = useState14(0);
|
|
13579
14214
|
const suggestionOffsetRef = useRef3(0);
|
|
13580
14215
|
const persistedModelRef = useRef3(null);
|
|
13581
|
-
|
|
14216
|
+
useEffect11(() => {
|
|
13582
14217
|
const ideName = getIDEName();
|
|
13583
14218
|
const isIDE = !["Terminal", "Windows Terminal"].includes(ideName) || !!process.env.VSC_TERMINAL_URL;
|
|
13584
14219
|
const graceTimer = setTimeout(() => {
|
|
@@ -13753,7 +14388,7 @@ function App({ args = [] }) {
|
|
|
13753
14388
|
}
|
|
13754
14389
|
}
|
|
13755
14390
|
};
|
|
13756
|
-
|
|
14391
|
+
useEffect11(() => {
|
|
13757
14392
|
const handleResize = () => {
|
|
13758
14393
|
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
13759
14394
|
setTerminalSize({
|
|
@@ -13766,18 +14401,18 @@ function App({ args = [] }) {
|
|
|
13766
14401
|
stdout.off("resize", handleResize);
|
|
13767
14402
|
};
|
|
13768
14403
|
}, [stdout]);
|
|
13769
|
-
const [thinkingLevel, setThinkingLevel] =
|
|
13770
|
-
const [aiProvider, setAiProvider] =
|
|
13771
|
-
const [setupStep, setSetupStep] =
|
|
13772
|
-
const [latestVer, setLatestVer] =
|
|
13773
|
-
const [showFullThinking, setShowFullThinking] =
|
|
13774
|
-
const [activeModel, setActiveModel] =
|
|
13775
|
-
const [janitorModel, setJanitorModel] =
|
|
13776
|
-
const [isInitializing, setIsInitializing] =
|
|
13777
|
-
const [isAppFocused, setIsAppFocused] =
|
|
14404
|
+
const [thinkingLevel, setThinkingLevel] = useState14("Medium");
|
|
14405
|
+
const [aiProvider, setAiProvider] = useState14("Google");
|
|
14406
|
+
const [setupStep, setSetupStep] = useState14(0);
|
|
14407
|
+
const [latestVer, setLatestVer] = useState14(null);
|
|
14408
|
+
const [showFullThinking, setShowFullThinking] = useState14(false);
|
|
14409
|
+
const [activeModel, setActiveModel] = useState14("gemma-4-31b-it");
|
|
14410
|
+
const [janitorModel, setJanitorModel] = useState14("gemma-4-26b-a4b-it");
|
|
14411
|
+
const [isInitializing, setIsInitializing] = useState14(true);
|
|
14412
|
+
const [isAppFocused, setIsAppFocused] = useState14(true);
|
|
13778
14413
|
const lastFocusEventTime = useRef3(0);
|
|
13779
|
-
const [apiKey, setApiKey] =
|
|
13780
|
-
const [tempKey, setTempKey] =
|
|
14414
|
+
const [apiKey, setApiKey] = useState14(null);
|
|
14415
|
+
const [tempKey, setTempKey] = useState14("");
|
|
13781
14416
|
const addShiftEnterBinding = async (ideName) => {
|
|
13782
14417
|
const kbPath = getKeybindingsPath(ideName);
|
|
13783
14418
|
if (!kbPath) return;
|
|
@@ -13828,35 +14463,35 @@ function App({ args = [] }) {
|
|
|
13828
14463
|
});
|
|
13829
14464
|
}
|
|
13830
14465
|
};
|
|
13831
|
-
const [activeView, setActiveView] =
|
|
13832
|
-
const [apiTier, setApiTier] =
|
|
13833
|
-
const [quotas, setQuotas] =
|
|
13834
|
-
const [inputConfig, setInputConfig] =
|
|
13835
|
-
const [systemSettings, setSystemSettings] =
|
|
13836
|
-
const [profileData, setProfileData] =
|
|
13837
|
-
const [imageSettings, setImageSettings] =
|
|
13838
|
-
const [sessionStats, setSessionStats] =
|
|
13839
|
-
const [sessionAgentCalls, setSessionAgentCalls] =
|
|
13840
|
-
const [sessionBackgroundCalls, setSessionBackgroundCalls] =
|
|
13841
|
-
const [sessionTotalTokens, setSessionTotalTokens] =
|
|
13842
|
-
const [chatTokens, setChatTokens] =
|
|
14466
|
+
const [activeView, setActiveView] = useState14("chat");
|
|
14467
|
+
const [apiTier, setApiTier] = useState14("Free");
|
|
14468
|
+
const [quotas, setQuotas] = useState14({ limitMode: "Daily", agentLimit: 99999999, tokenLimit: 99999999999999, backgroundLimit: 999999, searchLimit: 100, customModelId: "", customLimit: 0 });
|
|
14469
|
+
const [inputConfig, setInputConfig] = useState14(null);
|
|
14470
|
+
const [systemSettings, setSystemSettings] = useState14({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
|
|
14471
|
+
const [profileData, setProfileData] = useState14({ name: null, nickname: null, instructions: null });
|
|
14472
|
+
const [imageSettings, setImageSettings] = useState14({ keyType: "Default", quality: "Low-High", apiKey: "" });
|
|
14473
|
+
const [sessionStats, setSessionStats] = useState14({ tokens: 0 });
|
|
14474
|
+
const [sessionAgentCalls, setSessionAgentCalls] = useState14(0);
|
|
14475
|
+
const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState14(0);
|
|
14476
|
+
const [sessionTotalTokens, setSessionTotalTokens] = useState14(0);
|
|
14477
|
+
const [chatTokens, setChatTokens] = useState14(0);
|
|
13843
14478
|
const chatTokenStartRef = useRef3(0);
|
|
13844
|
-
const [sessionTotalCachedTokens, setSessionTotalCachedTokens] =
|
|
13845
|
-
const [sessionTotalCandidateTokens, setSessionTotalCandidateTokens] =
|
|
13846
|
-
const [sessionToolSuccess, setSessionToolSuccess] =
|
|
13847
|
-
const [sessionToolFailure, setSessionToolFailure] =
|
|
13848
|
-
const [sessionToolDenied, setSessionToolDenied] =
|
|
13849
|
-
const [sessionApiTime, setSessionApiTime] =
|
|
13850
|
-
const [sessionToolTime, setSessionToolTime] =
|
|
13851
|
-
const [sessionImageCount, setSessionImageCount] =
|
|
13852
|
-
const [sessionImageCredits, setSessionImageCredits] =
|
|
13853
|
-
const [dailyUsage, setDailyUsage] =
|
|
13854
|
-
const [monthlyUsage, setMonthlyUsage] =
|
|
13855
|
-
const [customPeriodUsage, setCustomPeriodUsage] =
|
|
13856
|
-
const [statsMode, setStatsMode] =
|
|
14479
|
+
const [sessionTotalCachedTokens, setSessionTotalCachedTokens] = useState14(0);
|
|
14480
|
+
const [sessionTotalCandidateTokens, setSessionTotalCandidateTokens] = useState14(0);
|
|
14481
|
+
const [sessionToolSuccess, setSessionToolSuccess] = useState14(0);
|
|
14482
|
+
const [sessionToolFailure, setSessionToolFailure] = useState14(0);
|
|
14483
|
+
const [sessionToolDenied, setSessionToolDenied] = useState14(0);
|
|
14484
|
+
const [sessionApiTime, setSessionApiTime] = useState14(0);
|
|
14485
|
+
const [sessionToolTime, setSessionToolTime] = useState14(0);
|
|
14486
|
+
const [sessionImageCount, setSessionImageCount] = useState14(0);
|
|
14487
|
+
const [sessionImageCredits, setSessionImageCredits] = useState14(0);
|
|
14488
|
+
const [dailyUsage, setDailyUsage] = useState14(null);
|
|
14489
|
+
const [monthlyUsage, setMonthlyUsage] = useState14(null);
|
|
14490
|
+
const [customPeriodUsage, setCustomPeriodUsage] = useState14(null);
|
|
14491
|
+
const [statsMode, setStatsMode] = useState14("daily");
|
|
13857
14492
|
const PLAYGROUND_CHAT_ID = "flow-playground";
|
|
13858
|
-
const [chatId, setChatId] =
|
|
13859
|
-
|
|
14493
|
+
const [chatId, setChatId] = useState14(args.includes("--playground") ? PLAYGROUND_CHAT_ID : generateChatId());
|
|
14494
|
+
useEffect11(() => {
|
|
13860
14495
|
const nextTokens = sessionTotalTokens - chatTokenStartRef.current;
|
|
13861
14496
|
setChatTokens(nextTokens);
|
|
13862
14497
|
if (chatId) {
|
|
@@ -13864,7 +14499,7 @@ function App({ args = [] }) {
|
|
|
13864
14499
|
});
|
|
13865
14500
|
}
|
|
13866
14501
|
}, [sessionTotalTokens, chatId, sessionStats.tokens]);
|
|
13867
|
-
|
|
14502
|
+
useEffect11(() => {
|
|
13868
14503
|
if (activeView === "apiTier") {
|
|
13869
14504
|
const load = async () => {
|
|
13870
14505
|
const d = await getDailyUsage();
|
|
@@ -13877,17 +14512,17 @@ function App({ args = [] }) {
|
|
|
13877
14512
|
load();
|
|
13878
14513
|
}
|
|
13879
14514
|
}, [activeView, quotas.resetDay]);
|
|
13880
|
-
const [activeCommand, setActiveCommand] =
|
|
13881
|
-
const [execOutput, setExecOutput] =
|
|
13882
|
-
const [isTerminalFocused, setIsTerminalFocused] =
|
|
13883
|
-
const [tick, setTick] =
|
|
14515
|
+
const [activeCommand, setActiveCommand] = useState14(null);
|
|
14516
|
+
const [execOutput, setExecOutput] = useState14("");
|
|
14517
|
+
const [isTerminalFocused, setIsTerminalFocused] = useState14(false);
|
|
14518
|
+
const [tick, setTick] = useState14(0);
|
|
13884
14519
|
const isFirstRender = useRef3(true);
|
|
13885
14520
|
const isSecondRender = useRef3(true);
|
|
13886
14521
|
const isThirdRender = useRef3(true);
|
|
13887
14522
|
const prevProviderRef = useRef3(aiProvider);
|
|
13888
14523
|
const originalAllowExternalAccessRef = useRef3(false);
|
|
13889
14524
|
const originalMemoryRef = useRef3(true);
|
|
13890
|
-
|
|
14525
|
+
useEffect11(() => {
|
|
13891
14526
|
if (prevProviderRef.current !== aiProvider) {
|
|
13892
14527
|
prevProviderRef.current = aiProvider;
|
|
13893
14528
|
const hasStandard = aiProvider === "DeepSeek" || aiProvider === "NVIDIA";
|
|
@@ -13900,7 +14535,7 @@ function App({ args = [] }) {
|
|
|
13900
14535
|
}
|
|
13901
14536
|
}
|
|
13902
14537
|
}, [aiProvider, activeModel, thinkingLevel]);
|
|
13903
|
-
|
|
14538
|
+
useEffect11(() => {
|
|
13904
14539
|
if (!apiKey) return;
|
|
13905
14540
|
if (isFirstRender.current) {
|
|
13906
14541
|
isFirstRender.current = false;
|
|
@@ -13974,15 +14609,15 @@ function App({ args = [] }) {
|
|
|
13974
14609
|
}, []);
|
|
13975
14610
|
const activeCommandRef = useRef3(null);
|
|
13976
14611
|
const execOutputRef = useRef3("");
|
|
13977
|
-
|
|
14612
|
+
useEffect11(() => {
|
|
13978
14613
|
activeCommandRef.current = activeCommand;
|
|
13979
14614
|
}, [activeCommand]);
|
|
13980
|
-
|
|
14615
|
+
useEffect11(() => {
|
|
13981
14616
|
execOutputRef.current = execOutput;
|
|
13982
14617
|
}, [execOutput]);
|
|
13983
|
-
const [autoAcceptWrites, setAutoAcceptWrites] =
|
|
13984
|
-
const [pendingApproval, setPendingApproval] =
|
|
13985
|
-
const [pendingAsk, setPendingAsk] =
|
|
14618
|
+
const [autoAcceptWrites, setAutoAcceptWrites] = useState14(false);
|
|
14619
|
+
const [pendingApproval, setPendingApproval] = useState14(null);
|
|
14620
|
+
const [pendingAsk, setPendingAsk] = useState14(null);
|
|
13986
14621
|
const resetPendingApproval = (decision) => {
|
|
13987
14622
|
setPendingApproval(null);
|
|
13988
14623
|
setActiveView("chat");
|
|
@@ -14001,9 +14636,10 @@ function App({ args = [] }) {
|
|
|
14001
14636
|
if (ms < 1e3) return `${ms}ms`;
|
|
14002
14637
|
return formatDuration(Math.floor(ms / 1e3));
|
|
14003
14638
|
};
|
|
14004
|
-
const [statusText, setStatusText] =
|
|
14005
|
-
const [wittyPhrase, setWittyPhrase] =
|
|
14006
|
-
|
|
14639
|
+
const [statusText, setStatusText] = useState14(null);
|
|
14640
|
+
const [wittyPhrase, setWittyPhrase] = useState14("");
|
|
14641
|
+
const [hasPasteBlock, setHasPasteBlock] = useState14(false);
|
|
14642
|
+
useEffect11(() => {
|
|
14007
14643
|
let interval;
|
|
14008
14644
|
if (statusText) {
|
|
14009
14645
|
const updatePhrase = () => {
|
|
@@ -14017,19 +14653,20 @@ function App({ args = [] }) {
|
|
|
14017
14653
|
}
|
|
14018
14654
|
return () => clearInterval(interval);
|
|
14019
14655
|
}, [statusText]);
|
|
14020
|
-
const [isSpinnerActive, setIsSpinnerActive] =
|
|
14021
|
-
const [isProcessing, setIsProcessing] =
|
|
14022
|
-
const [isCompressing, setIsCompressing] =
|
|
14023
|
-
const [escPressed, setEscPressed] =
|
|
14024
|
-
const [escTimer, setEscTimer] =
|
|
14025
|
-
const [escPressCount, setEscPressCount] =
|
|
14026
|
-
const [recentPrompts, setRecentPrompts] =
|
|
14656
|
+
const [isSpinnerActive, setIsSpinnerActive] = useState14(true);
|
|
14657
|
+
const [isProcessing, setIsProcessing] = useState14(false);
|
|
14658
|
+
const [isCompressing, setIsCompressing] = useState14(false);
|
|
14659
|
+
const [escPressed, setEscPressed] = useState14(false);
|
|
14660
|
+
const [escTimer, setEscTimer] = useState14(null);
|
|
14661
|
+
const [escPressCount, setEscPressCount] = useState14(0);
|
|
14662
|
+
const [recentPrompts, setRecentPrompts] = useState14([]);
|
|
14027
14663
|
const escDoubleTimerRef = useRef3(null);
|
|
14028
|
-
const
|
|
14029
|
-
const [
|
|
14030
|
-
const [
|
|
14031
|
-
|
|
14032
|
-
|
|
14664
|
+
const didSignalTerminationRef = useRef3(false);
|
|
14665
|
+
const [queuedPrompt, setQueuedPrompt] = useState14(null);
|
|
14666
|
+
const [resolutionData, setResolutionData] = useState14(null);
|
|
14667
|
+
const [tempModelOverride, setTempModelOverride] = useState14(null);
|
|
14668
|
+
useEffect11(() => setEscPressCount(0), [input]);
|
|
14669
|
+
const [messages, rawSetMessages] = useState14(() => {
|
|
14033
14670
|
const logoMsg = { id: "logo-" + Date.now(), role: "system", isLogo: true, isMeta: true };
|
|
14034
14671
|
const isHomeDir = process.cwd() === os4.homedir();
|
|
14035
14672
|
const isSystemDir = (() => {
|
|
@@ -14064,12 +14701,25 @@ function App({ args = [] }) {
|
|
|
14064
14701
|
}
|
|
14065
14702
|
return msgs;
|
|
14066
14703
|
});
|
|
14704
|
+
const setMessages = (value) => {
|
|
14705
|
+
rawSetMessages((prev) => {
|
|
14706
|
+
const next = typeof value === "function" ? value(prev) : value;
|
|
14707
|
+
if (next.length > 1) {
|
|
14708
|
+
const last = next[next.length - 1];
|
|
14709
|
+
const secondLast = next[next.length - 2];
|
|
14710
|
+
if (last?.text?.includes("Request Cancelled") && secondLast?.text?.includes("Request Cancelled")) {
|
|
14711
|
+
return next.slice(0, -1);
|
|
14712
|
+
}
|
|
14713
|
+
}
|
|
14714
|
+
return next;
|
|
14715
|
+
});
|
|
14716
|
+
};
|
|
14067
14717
|
const queuedPromptRef = useRef3(null);
|
|
14068
|
-
const [btwResponse, setBtwResponse] =
|
|
14069
|
-
const [showBtwBox, setShowBtwBox] =
|
|
14718
|
+
const [btwResponse, setBtwResponse] = useState14("");
|
|
14719
|
+
const [showBtwBox, setShowBtwBox] = useState14(false);
|
|
14070
14720
|
const btwResponseRef = useRef3("");
|
|
14071
14721
|
const btwClosedRef = useRef3(null);
|
|
14072
|
-
|
|
14722
|
+
useEffect11(() => {
|
|
14073
14723
|
if (messages.length === 0) return;
|
|
14074
14724
|
const lastMsg = messages[messages.length - 1];
|
|
14075
14725
|
if (lastMsg && (lastMsg.role === "agent" || lastMsg.role === "assistant")) {
|
|
@@ -14087,59 +14737,105 @@ function App({ args = [] }) {
|
|
|
14087
14737
|
}
|
|
14088
14738
|
}
|
|
14089
14739
|
}, [messages]);
|
|
14090
|
-
const [completedIndex, setCompletedIndex] =
|
|
14091
|
-
const [clearKey, setClearKey] =
|
|
14740
|
+
const [completedIndex, setCompletedIndex] = useState14(messages.length);
|
|
14741
|
+
const [clearKey, setClearKey] = useState14(0);
|
|
14742
|
+
const lastCompletedBlocksRef = useRef3([]);
|
|
14743
|
+
const cachedHistoryRef = useRef3({
|
|
14744
|
+
completedIndex: 0,
|
|
14745
|
+
columns: 0,
|
|
14746
|
+
historicalBlocks: [],
|
|
14747
|
+
seenSelections: /* @__PURE__ */ new Set()
|
|
14748
|
+
});
|
|
14092
14749
|
const parsedBlocks = useMemo2(() => {
|
|
14093
|
-
const completed = [];
|
|
14094
|
-
const active = [];
|
|
14095
14750
|
const columns = terminalSize.columns || 80;
|
|
14096
|
-
const
|
|
14097
|
-
|
|
14098
|
-
|
|
14099
|
-
const
|
|
14100
|
-
|
|
14101
|
-
|
|
14102
|
-
|
|
14103
|
-
|
|
14104
|
-
|
|
14105
|
-
|
|
14106
|
-
|
|
14107
|
-
|
|
14751
|
+
const SELECTION_REGEX = /Selection: (.*)/;
|
|
14752
|
+
let historicalBlocks = [];
|
|
14753
|
+
let seenAskSelections = /* @__PURE__ */ new Set();
|
|
14754
|
+
const isResize = cachedHistoryRef.current.columns !== columns;
|
|
14755
|
+
const isClear = completedIndex < cachedHistoryRef.current.completedIndex;
|
|
14756
|
+
if (isResize || isClear) {
|
|
14757
|
+
const completedMsgs = messages.slice(0, completedIndex);
|
|
14758
|
+
for (let i = 0; i < completedMsgs.length; i++) {
|
|
14759
|
+
const msg = completedMsgs[i];
|
|
14760
|
+
if (msg.isAskRecord && msg.text) {
|
|
14761
|
+
const match = msg.text.match(SELECTION_REGEX);
|
|
14762
|
+
if (match && match[1].trim()) {
|
|
14763
|
+
const selection = match[1].trim();
|
|
14764
|
+
if (seenAskSelections.has(selection)) continue;
|
|
14108
14765
|
seenAskSelections.add(selection);
|
|
14109
14766
|
}
|
|
14110
14767
|
}
|
|
14111
|
-
|
|
14112
|
-
|
|
14113
|
-
|
|
14114
|
-
|
|
14115
|
-
|
|
14116
|
-
|
|
14117
|
-
|
|
14118
|
-
|
|
14119
|
-
|
|
14120
|
-
|
|
14121
|
-
|
|
14768
|
+
const parsed = parseMessageToBlocks(msg, columns);
|
|
14769
|
+
for (let j = 0; j < parsed.completed.length; j++) historicalBlocks.push(parsed.completed[j]);
|
|
14770
|
+
for (let j = 0; j < parsed.active.length; j++) historicalBlocks.push(parsed.active[j]);
|
|
14771
|
+
}
|
|
14772
|
+
cachedHistoryRef.current = {
|
|
14773
|
+
completedIndex,
|
|
14774
|
+
columns,
|
|
14775
|
+
historicalBlocks,
|
|
14776
|
+
seenSelections: new Set(seenAskSelections)
|
|
14777
|
+
};
|
|
14778
|
+
} else {
|
|
14779
|
+
historicalBlocks = cachedHistoryRef.current.historicalBlocks;
|
|
14780
|
+
seenAskSelections = cachedHistoryRef.current.seenSelections;
|
|
14781
|
+
if (completedIndex > cachedHistoryRef.current.completedIndex) {
|
|
14782
|
+
historicalBlocks = [...historicalBlocks];
|
|
14783
|
+
seenAskSelections = new Set(seenAskSelections);
|
|
14784
|
+
const newMsgs = messages.slice(cachedHistoryRef.current.completedIndex, completedIndex);
|
|
14785
|
+
for (let i = 0; i < newMsgs.length; i++) {
|
|
14786
|
+
const msg = newMsgs[i];
|
|
14787
|
+
if (msg.isAskRecord && msg.text) {
|
|
14788
|
+
const match = msg.text.match(SELECTION_REGEX);
|
|
14789
|
+
if (match && match[1].trim()) {
|
|
14790
|
+
const selection = match[1].trim();
|
|
14791
|
+
if (seenAskSelections.has(selection)) continue;
|
|
14792
|
+
seenAskSelections.add(selection);
|
|
14793
|
+
}
|
|
14794
|
+
}
|
|
14795
|
+
const parsed = parseMessageToBlocks(msg, columns);
|
|
14796
|
+
for (let j = 0; j < parsed.completed.length; j++) historicalBlocks.push(parsed.completed[j]);
|
|
14797
|
+
for (let j = 0; j < parsed.active.length; j++) historicalBlocks.push(parsed.active[j]);
|
|
14798
|
+
}
|
|
14799
|
+
cachedHistoryRef.current = {
|
|
14800
|
+
completedIndex,
|
|
14801
|
+
columns,
|
|
14802
|
+
historicalBlocks,
|
|
14803
|
+
seenSelections: seenAskSelections
|
|
14804
|
+
};
|
|
14805
|
+
}
|
|
14806
|
+
}
|
|
14807
|
+
const activeMsgs = messages.slice(completedIndex);
|
|
14808
|
+
const streamingCompletedBlocks = [];
|
|
14809
|
+
const activeBlocks = [];
|
|
14810
|
+
for (let i = 0; i < activeMsgs.length; i++) {
|
|
14811
|
+
const msg = activeMsgs[i];
|
|
14812
|
+
if (msg.isAskRecord && msg.text) {
|
|
14813
|
+
const match = msg.text.match(SELECTION_REGEX);
|
|
14814
|
+
if (match && match[1].trim()) {
|
|
14815
|
+
const selection = match[1].trim();
|
|
14816
|
+
if (seenAskSelections.has(selection)) continue;
|
|
14817
|
+
}
|
|
14818
|
+
}
|
|
14122
14819
|
const parsed = parseMessageToBlocks(msg, columns);
|
|
14123
|
-
completed.push(
|
|
14124
|
-
active.push(
|
|
14125
|
-
}
|
|
14126
|
-
const
|
|
14127
|
-
|
|
14128
|
-
|
|
14129
|
-
|
|
14130
|
-
key: "memory-warning-block",
|
|
14820
|
+
for (let j = 0; j < parsed.completed.length; j++) streamingCompletedBlocks.push(parsed.completed[j]);
|
|
14821
|
+
for (let j = 0; j < parsed.active.length; j++) activeBlocks.push(parsed.active[j]);
|
|
14822
|
+
}
|
|
14823
|
+
const finalCompleted = historicalBlocks.concat(streamingCompletedBlocks);
|
|
14824
|
+
if (finalCompleted.length >= 75e3) {
|
|
14825
|
+
finalCompleted.push({
|
|
14826
|
+
key: `memory-warning-block-${finalCompleted.length}`,
|
|
14131
14827
|
msg: {
|
|
14132
14828
|
role: "system",
|
|
14133
14829
|
text: `\u26A0\uFE0F MEMORY WARNING: CHAT IS GETTING VERY LONG`,
|
|
14134
|
-
subText: `This session has reached ${
|
|
14830
|
+
subText: `This session has reached ${finalCompleted.length} blocks. To maintain optimal performance and prevent high memory usage, it is highly recommended to save and start a clean chat with /clear.`,
|
|
14135
14831
|
isHomeWarning: true
|
|
14136
14832
|
},
|
|
14137
14833
|
type: "full-message"
|
|
14138
14834
|
});
|
|
14139
14835
|
}
|
|
14140
14836
|
return {
|
|
14141
|
-
completed:
|
|
14142
|
-
active
|
|
14837
|
+
completed: finalCompleted,
|
|
14838
|
+
active: activeBlocks
|
|
14143
14839
|
};
|
|
14144
14840
|
}, [messages, completedIndex, terminalSize.columns]);
|
|
14145
14841
|
const isTerminalWaitingForInput = useMemo2(() => {
|
|
@@ -14147,7 +14843,7 @@ function App({ args = [] }) {
|
|
|
14147
14843
|
const lastChunk = execOutput.trim();
|
|
14148
14844
|
return lastChunk.endsWith("?") || lastChunk.endsWith(":") || /\[[yYnN/]+\]\s*$/.test(lastChunk) || /\([yYnN]\)\s*$/.test(lastChunk);
|
|
14149
14845
|
}, [activeCommand, execOutput]);
|
|
14150
|
-
|
|
14846
|
+
useInput9((inputText, key) => {
|
|
14151
14847
|
if (inputText === "\x1B[I" || inputText === "\x1B[O" || inputText === "[I" || inputText === "[O") {
|
|
14152
14848
|
return;
|
|
14153
14849
|
}
|
|
@@ -14246,16 +14942,11 @@ function App({ args = [] }) {
|
|
|
14246
14942
|
return;
|
|
14247
14943
|
}
|
|
14248
14944
|
if (isProcessing || activeCommand) {
|
|
14249
|
-
|
|
14250
|
-
|
|
14251
|
-
|
|
14252
|
-
|
|
14253
|
-
|
|
14254
|
-
signalTermination();
|
|
14255
|
-
terminateActiveCommand();
|
|
14256
|
-
setEscPressed(false);
|
|
14257
|
-
if (escTimer) clearTimeout(escTimer);
|
|
14258
|
-
}
|
|
14945
|
+
didSignalTerminationRef.current = true;
|
|
14946
|
+
signalTermination();
|
|
14947
|
+
terminateActiveCommand();
|
|
14948
|
+
setEscPressed(false);
|
|
14949
|
+
if (escTimer) clearTimeout(escTimer);
|
|
14259
14950
|
} else {
|
|
14260
14951
|
if (activeView === "revert") {
|
|
14261
14952
|
setActiveView("chat");
|
|
@@ -14333,7 +15024,7 @@ function App({ args = [] }) {
|
|
|
14333
15024
|
setInput((prev) => prev.replace(/\\\r?$/, "").replace(/\r?$/, "") + "\n");
|
|
14334
15025
|
}
|
|
14335
15026
|
});
|
|
14336
|
-
|
|
15027
|
+
useEffect11(() => {
|
|
14337
15028
|
process.stdout.write("\x1B[?1004h");
|
|
14338
15029
|
const onData = (data) => {
|
|
14339
15030
|
const str = data.toString();
|
|
@@ -14351,7 +15042,7 @@ function App({ args = [] }) {
|
|
|
14351
15042
|
process.stdin.off("data", onData);
|
|
14352
15043
|
};
|
|
14353
15044
|
}, []);
|
|
14354
|
-
|
|
15045
|
+
useEffect11(() => {
|
|
14355
15046
|
async function init() {
|
|
14356
15047
|
try {
|
|
14357
15048
|
const pkg = JSON.parse(fs22.readFileSync(path20.join(process.cwd(), "package.json"), "utf8"));
|
|
@@ -14570,7 +15261,7 @@ function App({ args = [] }) {
|
|
|
14570
15261
|
}
|
|
14571
15262
|
init();
|
|
14572
15263
|
}, []);
|
|
14573
|
-
|
|
15264
|
+
useEffect11(() => {
|
|
14574
15265
|
let timer;
|
|
14575
15266
|
if (confirmExit) {
|
|
14576
15267
|
setExitCountdown(10);
|
|
@@ -14588,7 +15279,7 @@ function App({ args = [] }) {
|
|
|
14588
15279
|
if (timer) clearInterval(timer);
|
|
14589
15280
|
};
|
|
14590
15281
|
}, [confirmExit]);
|
|
14591
|
-
|
|
15282
|
+
useEffect11(() => {
|
|
14592
15283
|
if (!isInitializing) {
|
|
14593
15284
|
const modelToSave = parsedArgs.model && activeModel === parsedArgs.model ? persistedModelRef.current : activeModel;
|
|
14594
15285
|
let settingsToSave = systemSettings;
|
|
@@ -14638,7 +15329,7 @@ function App({ args = [] }) {
|
|
|
14638
15329
|
}
|
|
14639
15330
|
};
|
|
14640
15331
|
const lastSavedTimeRef = useRef3(SESSION_START_TIME);
|
|
14641
|
-
|
|
15332
|
+
useEffect11(() => {
|
|
14642
15333
|
if (activeView === "exit") {
|
|
14643
15334
|
const flush = async () => {
|
|
14644
15335
|
const now = Date.now();
|
|
@@ -14656,7 +15347,7 @@ function App({ args = [] }) {
|
|
|
14656
15347
|
return () => clearTimeout(timer);
|
|
14657
15348
|
}
|
|
14658
15349
|
}, [activeView]);
|
|
14659
|
-
|
|
15350
|
+
useEffect11(() => {
|
|
14660
15351
|
const interval = setInterval(async () => {
|
|
14661
15352
|
if (!isInitializing) {
|
|
14662
15353
|
const now = Date.now();
|
|
@@ -14666,7 +15357,7 @@ function App({ args = [] }) {
|
|
|
14666
15357
|
lastSavedTimeRef.current += deltaSecs * 1e3;
|
|
14667
15358
|
}
|
|
14668
15359
|
}
|
|
14669
|
-
},
|
|
15360
|
+
}, 2e3);
|
|
14670
15361
|
return () => clearInterval(interval);
|
|
14671
15362
|
}, [isInitializing]);
|
|
14672
15363
|
const COMMANDS = [
|
|
@@ -14682,32 +15373,6 @@ function App({ args = [] }) {
|
|
|
14682
15373
|
{ cmd: "/export", desc: "Export current chat in a .txt file" },
|
|
14683
15374
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
14684
15375
|
{ cmd: "/btw", desc: "Ask a question without intefering with ongoing tasks" },
|
|
14685
|
-
// {
|
|
14686
|
-
// cmd: '/image', desc: 'Generate images using Pollinations', subs: [
|
|
14687
|
-
// {
|
|
14688
|
-
// cmd: 'setup', desc: 'Configure defaults', subs: [
|
|
14689
|
-
// {
|
|
14690
|
-
// cmd: 'key', desc: 'Set API key strategy', subs: [
|
|
14691
|
-
// { cmd: 'default', desc: 'Default (Quota: Dynamic 25 max/hr)' },
|
|
14692
|
-
// { cmd: 'custom', desc: 'Custom Key' }
|
|
14693
|
-
// ]
|
|
14694
|
-
// },
|
|
14695
|
-
// {
|
|
14696
|
-
// cmd: 'quality', desc: 'Set default quality', subs: [
|
|
14697
|
-
// { cmd: 'low', desc: imageSettings?.keyType === 'Custom' ? '(0.001/img)' : '(1/img)' },
|
|
14698
|
-
// { cmd: 'low-high', desc: imageSettings?.keyType === 'Custom' ? '(0.002/img)' : '(2/img)' },
|
|
14699
|
-
// { cmd: 'medium', desc: imageSettings?.keyType === 'Custom' ? '(0.008/img)' : '(8/img)' },
|
|
14700
|
-
// { cmd: 'medium-high', desc: imageSettings?.keyType === 'Custom' ? '(0.01/img)' : '(10/img)' },
|
|
14701
|
-
// { cmd: 'high', desc: imageSettings?.keyType === 'Custom' ? '(0.045/img)' : '(45/img)' },
|
|
14702
|
-
// { cmd: 'ultra', desc: imageSettings?.keyType === 'Custom' ? '(0.0488/img)' : '(49/img)' },
|
|
14703
|
-
// { cmd: 'premium', desc: imageSettings?.keyType === 'Custom' ? '(0.1/img)' : '(100/img)' }
|
|
14704
|
-
// ]
|
|
14705
|
-
// }
|
|
14706
|
-
// ]
|
|
14707
|
-
// },
|
|
14708
|
-
// { cmd: 'stats', desc: 'Show remaining credits or Pollinations balance status' }
|
|
14709
|
-
// ]
|
|
14710
|
-
// },
|
|
14711
15376
|
{
|
|
14712
15377
|
cmd: "/mode",
|
|
14713
15378
|
desc: "Toggle Flux/Flow modes",
|
|
@@ -14749,7 +15414,7 @@ function App({ args = [] }) {
|
|
|
14749
15414
|
},
|
|
14750
15415
|
{
|
|
14751
15416
|
cmd: "/model",
|
|
14752
|
-
desc: "
|
|
15417
|
+
desc: "Select Agent Model",
|
|
14753
15418
|
subs: aiProvider === "OpenRouter" ? apiTier === "Free" ? [
|
|
14754
15419
|
{
|
|
14755
15420
|
cmd: "google/gemma-4-31b-it:free",
|
|
@@ -14761,11 +15426,11 @@ function App({ args = [] }) {
|
|
|
14761
15426
|
},
|
|
14762
15427
|
{
|
|
14763
15428
|
cmd: "qwen/qwen3-coder:free",
|
|
14764
|
-
desc: ""
|
|
15429
|
+
desc: "Text Only"
|
|
14765
15430
|
},
|
|
14766
15431
|
{
|
|
14767
15432
|
cmd: "z-ai/glm-4.5-air:free",
|
|
14768
|
-
desc: ""
|
|
15433
|
+
desc: "Text Only"
|
|
14769
15434
|
}
|
|
14770
15435
|
] : [
|
|
14771
15436
|
{
|
|
@@ -14794,19 +15459,19 @@ function App({ args = [] }) {
|
|
|
14794
15459
|
},
|
|
14795
15460
|
{
|
|
14796
15461
|
cmd: "deepseek/deepseek-v4-pro",
|
|
14797
|
-
desc: ""
|
|
15462
|
+
desc: "Text Only"
|
|
14798
15463
|
},
|
|
14799
15464
|
{
|
|
14800
15465
|
cmd: "deepseek/deepseek-v4-flash",
|
|
14801
|
-
desc: ""
|
|
15466
|
+
desc: "Text Only"
|
|
14802
15467
|
},
|
|
14803
15468
|
{
|
|
14804
15469
|
cmd: "xiaomi/mimo-v2.5-pro",
|
|
14805
|
-
desc: ""
|
|
15470
|
+
desc: "Text Only"
|
|
14806
15471
|
},
|
|
14807
15472
|
{
|
|
14808
15473
|
cmd: "z-ai/glm-5",
|
|
14809
|
-
desc: ""
|
|
15474
|
+
desc: "Text Only"
|
|
14810
15475
|
},
|
|
14811
15476
|
{
|
|
14812
15477
|
cmd: "openai/gpt-5.2-codex",
|
|
@@ -14827,106 +15492,122 @@ function App({ args = [] }) {
|
|
|
14827
15492
|
] : aiProvider === "DeepSeek" ? [
|
|
14828
15493
|
{
|
|
14829
15494
|
cmd: "deepseek-v4-flash",
|
|
14830
|
-
desc: "Fast & Efficient"
|
|
15495
|
+
desc: "Fast & Efficient (Text Only)"
|
|
14831
15496
|
},
|
|
14832
15497
|
{
|
|
14833
15498
|
cmd: "deepseek-v4-pro",
|
|
14834
|
-
desc: "High-Intelligence Reasoning"
|
|
15499
|
+
desc: "High-Intelligence Reasoning (Text Only)"
|
|
14835
15500
|
}
|
|
14836
15501
|
] : aiProvider === "NVIDIA" ? [
|
|
15502
|
+
// --- Kimi (Moonshot AI) ---
|
|
14837
15503
|
{
|
|
14838
15504
|
cmd: "moonshotai/kimi-k2.6",
|
|
14839
15505
|
desc: "Multimodal"
|
|
14840
15506
|
},
|
|
15507
|
+
// --- DeepSeek Family ---
|
|
14841
15508
|
{
|
|
14842
|
-
cmd: "
|
|
14843
|
-
desc: ""
|
|
15509
|
+
cmd: "deepseek-ai/deepseek-v4-flash",
|
|
15510
|
+
desc: "Text Only"
|
|
14844
15511
|
},
|
|
14845
15512
|
{
|
|
14846
|
-
cmd: "
|
|
14847
|
-
desc: ""
|
|
15513
|
+
cmd: "deepseek-ai/deepseek-v4-pro",
|
|
15514
|
+
desc: "Text Only"
|
|
14848
15515
|
},
|
|
15516
|
+
// --- StepFun ---
|
|
14849
15517
|
{
|
|
14850
|
-
cmd: "
|
|
14851
|
-
desc: ""
|
|
15518
|
+
cmd: "stepfun-ai/step-3.7-flash",
|
|
15519
|
+
desc: "Multimodal"
|
|
14852
15520
|
},
|
|
15521
|
+
// --- Gemma Family (Google) ---
|
|
14853
15522
|
{
|
|
14854
|
-
cmd: "
|
|
14855
|
-
desc: ""
|
|
15523
|
+
cmd: "google/gemma-4-31b-it",
|
|
15524
|
+
desc: "Multimodal"
|
|
14856
15525
|
},
|
|
14857
15526
|
{
|
|
14858
|
-
cmd: "
|
|
14859
|
-
desc: ""
|
|
15527
|
+
cmd: "google/diffusiongemma-26b-a4b-it",
|
|
15528
|
+
desc: "Mega Fast [Experimental]"
|
|
14860
15529
|
},
|
|
15530
|
+
// --- Mistral ---
|
|
14861
15531
|
{
|
|
14862
15532
|
cmd: "mistralai/mistral-medium-3.5-128b",
|
|
14863
|
-
desc: ""
|
|
15533
|
+
desc: "Multimodal"
|
|
15534
|
+
},
|
|
15535
|
+
// --- GPT Open Source Series (OpenAI) ---
|
|
15536
|
+
{
|
|
15537
|
+
cmd: "openai/gpt-oss-20b",
|
|
15538
|
+
desc: "Text Only"
|
|
15539
|
+
},
|
|
15540
|
+
{
|
|
15541
|
+
cmd: "openai/gpt-oss-120b",
|
|
15542
|
+
desc: "Text Only"
|
|
14864
15543
|
},
|
|
15544
|
+
// --- GLM (Zhipu AI) ---
|
|
14865
15545
|
{
|
|
14866
15546
|
cmd: "z-ai/glm-5.1",
|
|
14867
|
-
desc: ""
|
|
15547
|
+
desc: "Text Only"
|
|
14868
15548
|
},
|
|
15549
|
+
// --- MiniMax Family ---
|
|
14869
15550
|
{
|
|
14870
|
-
cmd: "
|
|
14871
|
-
desc: "
|
|
15551
|
+
cmd: "minimaxai/minimax-m2.7",
|
|
15552
|
+
desc: "Text Only"
|
|
14872
15553
|
},
|
|
14873
15554
|
{
|
|
14874
15555
|
cmd: "minimaxai/minimax-m3",
|
|
14875
|
-
desc: ""
|
|
15556
|
+
desc: "Text Only"
|
|
14876
15557
|
}
|
|
14877
15558
|
] : apiTier === "Free" ? [
|
|
14878
15559
|
{
|
|
14879
15560
|
cmd: "gemma-4-26b-a4b-it",
|
|
14880
|
-
desc: "Standard & Faster"
|
|
15561
|
+
desc: "Standard & Faster (Multimodal)"
|
|
14881
15562
|
},
|
|
14882
15563
|
{
|
|
14883
15564
|
cmd: "gemma-4-31b-it",
|
|
14884
|
-
desc: "Standard Default"
|
|
15565
|
+
desc: "Standard Default (Multimodal)"
|
|
14885
15566
|
},
|
|
14886
15567
|
{
|
|
14887
15568
|
cmd: "gemini-2.5-flash-lite",
|
|
14888
|
-
desc: "Fast & Cheap (Limited Free Quota
|
|
15569
|
+
desc: "Fast & Cheap (Multimodal) [Limited Free Quota]"
|
|
14889
15570
|
},
|
|
14890
15571
|
{
|
|
14891
15572
|
cmd: "gemini-2.5-flash",
|
|
14892
|
-
desc: "Fast & Reliable (Limited Free Quota
|
|
15573
|
+
desc: "Fast & Reliable (Multimodal) [Limited Free Quota]"
|
|
14893
15574
|
},
|
|
14894
15575
|
{
|
|
14895
15576
|
cmd: "gemini-3-flash-preview",
|
|
14896
|
-
desc: "Fast & Lightweight (Limited Free Quota
|
|
15577
|
+
desc: "Fast & Lightweight (Multimodal) [Limited Free Quota]"
|
|
14897
15578
|
},
|
|
14898
15579
|
{
|
|
14899
15580
|
cmd: "gemini-3.5-flash",
|
|
14900
|
-
desc: "Flash Latest (Limited Free Quota
|
|
15581
|
+
desc: "Flash Latest (Multimodal) [Limited Free Quota] Instability Issues"
|
|
14901
15582
|
}
|
|
14902
15583
|
] : [
|
|
14903
15584
|
{
|
|
14904
15585
|
cmd: "gemini-2.5-flash-lite",
|
|
14905
|
-
desc: "Fast & Cheap"
|
|
15586
|
+
desc: "Fast & Cheap (Multimodal)"
|
|
14906
15587
|
},
|
|
14907
15588
|
{
|
|
14908
15589
|
cmd: "gemini-2.5-flash",
|
|
14909
|
-
desc: "Fast & Reliable"
|
|
15590
|
+
desc: "Fast & Reliable (Multimodal)"
|
|
14910
15591
|
},
|
|
14911
15592
|
{
|
|
14912
15593
|
cmd: "gemini-2.5-pro",
|
|
14913
|
-
desc: "Last gen Pro reasoning"
|
|
15594
|
+
desc: "Last gen Pro reasoning (Multimodal)"
|
|
14914
15595
|
},
|
|
14915
15596
|
{
|
|
14916
15597
|
cmd: "gemini-3.1-flash-lite",
|
|
14917
|
-
desc: "Ultra-Fast & Lite"
|
|
15598
|
+
desc: "Ultra-Fast & Lite (Multimodal)"
|
|
14918
15599
|
},
|
|
14919
15600
|
{
|
|
14920
15601
|
cmd: "gemini-3-flash-preview",
|
|
14921
|
-
desc: "Default, Fast & Lightweight"
|
|
15602
|
+
desc: "Default, Fast & Lightweight (Multimodal)"
|
|
14922
15603
|
},
|
|
14923
15604
|
{
|
|
14924
15605
|
cmd: "gemini-3.5-flash",
|
|
14925
|
-
desc: "Flash Latest
|
|
15606
|
+
desc: "Flash Latest (Multimodal) [Instability Issues]"
|
|
14926
15607
|
},
|
|
14927
15608
|
{
|
|
14928
15609
|
cmd: "gemini-3.1-pro-preview",
|
|
14929
|
-
desc: "Pro Reasoning"
|
|
15610
|
+
desc: "Pro Reasoning (Multimodal)"
|
|
14930
15611
|
}
|
|
14931
15612
|
]
|
|
14932
15613
|
},
|
|
@@ -14943,7 +15624,7 @@ function App({ args = [] }) {
|
|
|
14943
15624
|
cmd: "/fluxflow",
|
|
14944
15625
|
desc: "Project management",
|
|
14945
15626
|
subs: [
|
|
14946
|
-
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
15627
|
+
{ cmd: "init", desc: "Create empty FluxFlow.md template" }
|
|
14947
15628
|
]
|
|
14948
15629
|
},
|
|
14949
15630
|
{
|
|
@@ -14958,8 +15639,8 @@ function App({ args = [] }) {
|
|
|
14958
15639
|
cmd: "/update",
|
|
14959
15640
|
desc: "Check/Install updates",
|
|
14960
15641
|
subs: [
|
|
14961
|
-
{ cmd: "
|
|
14962
|
-
{ cmd: "
|
|
15642
|
+
{ cmd: "latest", desc: "Install latest release" },
|
|
15643
|
+
{ cmd: "check", desc: "Check for new version" }
|
|
14963
15644
|
]
|
|
14964
15645
|
}
|
|
14965
15646
|
];
|
|
@@ -14977,6 +15658,7 @@ function App({ args = [] }) {
|
|
|
14977
15658
|
setInputKey((prev) => prev + 1);
|
|
14978
15659
|
return;
|
|
14979
15660
|
}
|
|
15661
|
+
didSignalTerminationRef.current = false;
|
|
14980
15662
|
const normalizedValue = value.replace(/\r\n/g, "\n").replace(/\r/g, "\n").trimEnd();
|
|
14981
15663
|
if (normalizedValue.endsWith("\\")) {
|
|
14982
15664
|
setInput(normalizedValue.slice(0, -1) + "\n");
|
|
@@ -15038,6 +15720,7 @@ ${cleanText}`, color: "magenta" }];
|
|
|
15038
15720
|
const target = h[targetId] || Object.values(h).find((h2) => h2.name.toLowerCase() === targetId.toLowerCase());
|
|
15039
15721
|
if (target) {
|
|
15040
15722
|
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
15723
|
+
clearBlocksCache();
|
|
15041
15724
|
setChatId(targetId);
|
|
15042
15725
|
const savedData = await loadChatContext(targetId);
|
|
15043
15726
|
chatTokenStartRef.current = sessionTotalTokens - savedData.total;
|
|
@@ -15112,12 +15795,16 @@ ${cleanText}`, color: "magenta" }];
|
|
|
15112
15795
|
case "/clear": {
|
|
15113
15796
|
if (stdout) {
|
|
15114
15797
|
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
15798
|
+
if (stdout.isTTY) {
|
|
15799
|
+
stdout.write("\x1B[?2004h");
|
|
15800
|
+
}
|
|
15115
15801
|
}
|
|
15116
15802
|
setMessages([
|
|
15117
15803
|
{ id: "logo-" + Date.now(), role: "system", isLogo: true, isMeta: true }
|
|
15118
15804
|
]);
|
|
15119
15805
|
setCompletedIndex(1);
|
|
15120
15806
|
setClearKey((prev) => prev + 1);
|
|
15807
|
+
clearBlocksCache();
|
|
15121
15808
|
if (parsedArgs.playground) {
|
|
15122
15809
|
parsedArgs.playground = false;
|
|
15123
15810
|
deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
|
|
@@ -15163,6 +15850,14 @@ ${cleanText}`, color: "magenta" }];
|
|
|
15163
15850
|
setIsExpanded(false);
|
|
15164
15851
|
setChatTokens(0);
|
|
15165
15852
|
chatTokenStartRef.current = sessionTotalTokens;
|
|
15853
|
+
setTimeout(() => {
|
|
15854
|
+
if (global.gc) {
|
|
15855
|
+
try {
|
|
15856
|
+
global.gc();
|
|
15857
|
+
} catch (e) {
|
|
15858
|
+
}
|
|
15859
|
+
}
|
|
15860
|
+
}, 500);
|
|
15166
15861
|
break;
|
|
15167
15862
|
}
|
|
15168
15863
|
case "/revert": {
|
|
@@ -15178,6 +15873,14 @@ ${cleanText}`, color: "magenta" }];
|
|
|
15178
15873
|
});
|
|
15179
15874
|
}
|
|
15180
15875
|
});
|
|
15876
|
+
setTimeout(() => {
|
|
15877
|
+
if (global.gc) {
|
|
15878
|
+
try {
|
|
15879
|
+
global.gc();
|
|
15880
|
+
} catch (e) {
|
|
15881
|
+
}
|
|
15882
|
+
}
|
|
15883
|
+
}, 500);
|
|
15181
15884
|
break;
|
|
15182
15885
|
}
|
|
15183
15886
|
case "/mode": {
|
|
@@ -15784,6 +16487,26 @@ ${timestamp}` };
|
|
|
15784
16487
|
return [...prev, userMessage];
|
|
15785
16488
|
});
|
|
15786
16489
|
const streamChat = async () => {
|
|
16490
|
+
let didAppendCancel = false;
|
|
16491
|
+
const appendCancelMessage = () => {
|
|
16492
|
+
if (didAppendCancel) return;
|
|
16493
|
+
didAppendCancel = true;
|
|
16494
|
+
setMessages((prev) => {
|
|
16495
|
+
const lastMsg = prev[prev.length - 1];
|
|
16496
|
+
if (lastMsg && lastMsg.text && lastMsg.text.includes("Request Cancelled")) {
|
|
16497
|
+
return prev;
|
|
16498
|
+
}
|
|
16499
|
+
const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
|
|
16500
|
+
const newMsgs = [...updatedPrev, {
|
|
16501
|
+
id: "cancel-" + Date.now(),
|
|
16502
|
+
role: "system",
|
|
16503
|
+
text: "\n\n\x1B[33m\u2139 Request Cancelled\x1B[0m",
|
|
16504
|
+
isMeta: true
|
|
16505
|
+
}];
|
|
16506
|
+
setCompletedIndex(newMsgs.length);
|
|
16507
|
+
return newMsgs;
|
|
16508
|
+
});
|
|
16509
|
+
};
|
|
15787
16510
|
let hasFiredJanitor = false;
|
|
15788
16511
|
setIsProcessing(true);
|
|
15789
16512
|
setIsExpanded(false);
|
|
@@ -15976,7 +16699,14 @@ Selection: ${val}`,
|
|
|
15976
16699
|
let toolCallBalance = 0;
|
|
15977
16700
|
let inToolCallString = null;
|
|
15978
16701
|
const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
|
|
16702
|
+
const bullyTheBug = path20.join(DATA_DIR, "padding");
|
|
15979
16703
|
for await (const packet of stream) {
|
|
16704
|
+
if (packet.type === "interactive_turn_finished") {
|
|
16705
|
+
fs22.writeFileSync(bullyTheBug, "pad_0xa\n");
|
|
16706
|
+
} else {
|
|
16707
|
+
fs22.appendFileSync(bullyTheBug, "\r");
|
|
16708
|
+
parsedBlocks.completed = [];
|
|
16709
|
+
}
|
|
15980
16710
|
if (isFirstPacket && packet.type === "text") {
|
|
15981
16711
|
apiStart = Date.now();
|
|
15982
16712
|
isFirstPacket = false;
|
|
@@ -15987,17 +16717,7 @@ Selection: ${val}`,
|
|
|
15987
16717
|
sendStatus(packet.content);
|
|
15988
16718
|
}
|
|
15989
16719
|
if (packet.content === "Request Cancelled") {
|
|
15990
|
-
|
|
15991
|
-
const updatedPrev = prev.map((m) => m.isStreaming ? { ...m, isStreaming: false } : m);
|
|
15992
|
-
const newMsgs = [...updatedPrev, {
|
|
15993
|
-
id: "cancel-" + Date.now(),
|
|
15994
|
-
role: "system",
|
|
15995
|
-
text: "\n\n\x1B[33m\u2139 Request Cancelled\x1B[0m",
|
|
15996
|
-
isMeta: true
|
|
15997
|
-
}];
|
|
15998
|
-
setCompletedIndex(newMsgs.length);
|
|
15999
|
-
return newMsgs;
|
|
16000
|
-
});
|
|
16720
|
+
appendCancelMessage();
|
|
16001
16721
|
}
|
|
16002
16722
|
continue;
|
|
16003
16723
|
}
|
|
@@ -16036,6 +16756,14 @@ Selection: ${val}`,
|
|
|
16036
16756
|
setCompletedIndex(newMsgs.length);
|
|
16037
16757
|
return newMsgs;
|
|
16038
16758
|
});
|
|
16759
|
+
setTimeout(() => {
|
|
16760
|
+
if (global.gc) {
|
|
16761
|
+
try {
|
|
16762
|
+
global.gc();
|
|
16763
|
+
} catch (e) {
|
|
16764
|
+
}
|
|
16765
|
+
}
|
|
16766
|
+
}, 100);
|
|
16039
16767
|
continue;
|
|
16040
16768
|
}
|
|
16041
16769
|
if (packet.type === "interactive_turn_finished") {
|
|
@@ -16244,29 +16972,31 @@ Selection: ${val}`,
|
|
|
16244
16972
|
}
|
|
16245
16973
|
if (inThinkMode && currentThinkId) {
|
|
16246
16974
|
setMessages((prev) => {
|
|
16975
|
+
const next = [...prev];
|
|
16247
16976
|
let transitioning = false;
|
|
16248
16977
|
let transitionContent = "";
|
|
16249
|
-
|
|
16250
|
-
if (
|
|
16251
|
-
const newText =
|
|
16978
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
16979
|
+
if (next[i].id === currentThinkId) {
|
|
16980
|
+
const newText = next[i].text + chunkText;
|
|
16252
16981
|
if (newText.toLowerCase().includes("</think>")) {
|
|
16253
16982
|
transitioning = true;
|
|
16254
16983
|
const parts = newText.split(/<\/think>/gi);
|
|
16255
16984
|
transitionContent = parts.slice(1).join("</think>") || "";
|
|
16256
|
-
const startTime =
|
|
16985
|
+
const startTime = next[i].startTime || parseInt(String(next[i].id).split("-")[1]) || Date.now();
|
|
16257
16986
|
const duration = Date.now() - startTime;
|
|
16258
|
-
|
|
16987
|
+
next[i] = { ...next[i], text: parts[0], isStreaming: false, duration };
|
|
16988
|
+
} else {
|
|
16989
|
+
next[i] = { ...next[i], text: newText, isStreaming: true };
|
|
16259
16990
|
}
|
|
16260
|
-
|
|
16991
|
+
break;
|
|
16261
16992
|
}
|
|
16262
|
-
|
|
16263
|
-
});
|
|
16993
|
+
}
|
|
16264
16994
|
if (transitioning) {
|
|
16265
16995
|
inThinkMode = false;
|
|
16266
16996
|
currentAgentId = "agent-" + Date.now();
|
|
16267
|
-
|
|
16997
|
+
next.push({ id: currentAgentId, role: "agent", text: transitionContent.replace(/<\/?(think|thought)>/gi, ""), isStreaming: true });
|
|
16268
16998
|
}
|
|
16269
|
-
return
|
|
16999
|
+
return next;
|
|
16270
17000
|
});
|
|
16271
17001
|
} else if (!inThinkMode) {
|
|
16272
17002
|
const chunkLower2 = chunkText.toLowerCase();
|
|
@@ -16277,9 +17007,16 @@ Selection: ${val}`,
|
|
|
16277
17007
|
currentAgentId = "agent-" + Date.now();
|
|
16278
17008
|
setMessages((prev) => [...prev, { id: currentAgentId, role: "agent", text: chunkText, isStreaming: true }]);
|
|
16279
17009
|
} else {
|
|
16280
|
-
setMessages((prev) =>
|
|
16281
|
-
|
|
16282
|
-
|
|
17010
|
+
setMessages((prev) => {
|
|
17011
|
+
const next = [...prev];
|
|
17012
|
+
for (let i = next.length - 1; i >= 0; i--) {
|
|
17013
|
+
if (next[i].id === currentAgentId) {
|
|
17014
|
+
next[i] = { ...next[i], text: next[i].text + chunkText, isStreaming: true };
|
|
17015
|
+
break;
|
|
17016
|
+
}
|
|
17017
|
+
}
|
|
17018
|
+
return next;
|
|
17019
|
+
});
|
|
16283
17020
|
}
|
|
16284
17021
|
}
|
|
16285
17022
|
}
|
|
@@ -16293,6 +17030,9 @@ Selection: ${val}`,
|
|
|
16293
17030
|
} finally {
|
|
16294
17031
|
setIsProcessing(false);
|
|
16295
17032
|
setStatusText(null);
|
|
17033
|
+
if (didSignalTerminationRef.current) {
|
|
17034
|
+
appendCancelMessage();
|
|
17035
|
+
}
|
|
16296
17036
|
if (!hasFiredJanitor) {
|
|
16297
17037
|
if (process.stdout.isTTY) {
|
|
16298
17038
|
process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
|
|
@@ -16384,7 +17124,7 @@ Selection: ${val}`,
|
|
|
16384
17124
|
}
|
|
16385
17125
|
return [];
|
|
16386
17126
|
}, [input, isFilePickerDismissed]);
|
|
16387
|
-
|
|
17127
|
+
useEffect11(() => {
|
|
16388
17128
|
setSelectedIndex(0);
|
|
16389
17129
|
}, [suggestions]);
|
|
16390
17130
|
const CustomMenuItem = ({ label: label2, isSelected }) => {
|
|
@@ -16881,6 +17621,7 @@ Selection: ${val}`,
|
|
|
16881
17621
|
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
16882
17622
|
}
|
|
16883
17623
|
setClearKey((prev) => prev + 1);
|
|
17624
|
+
clearBlocksCache();
|
|
16884
17625
|
const targetIdx = messages.findLastIndex(
|
|
16885
17626
|
(m) => m.role === "user" && m.text && (m.text.startsWith(targetPrompt) || m.text.includes(targetPrompt))
|
|
16886
17627
|
);
|
|
@@ -16933,6 +17674,7 @@ Selection: ${val}`,
|
|
|
16933
17674
|
const h = await loadHistory();
|
|
16934
17675
|
if (h[id]) {
|
|
16935
17676
|
stdout.write("\x1B[2J\x1B[3J\x1B[H");
|
|
17677
|
+
clearBlocksCache();
|
|
16936
17678
|
setChatId(id);
|
|
16937
17679
|
const savedData = await loadChatContext(id);
|
|
16938
17680
|
chatTokenStartRef.current = sessionTotalTokens - savedData.total;
|
|
@@ -17147,7 +17889,7 @@ Selection: ${val}`,
|
|
|
17147
17889
|
}
|
|
17148
17890
|
)));
|
|
17149
17891
|
default:
|
|
17150
|
-
return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box15, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text16, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text16, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, null, statusText ? /* @__PURE__ */ React15.createElement(Box15, { gap: 1 }, /* @__PURE__ */ React15.createElement(dist_default, { colors: ["#001a1a", "#080510", "#12021c"] }, /* @__PURE__ */ React15.createElement(build_default, null)), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true, italic: true }, statusText)) : /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box15, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text16, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
|
|
17892
|
+
return /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, showBtwBox && btwResponse && /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%", marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Box15, { justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Text16, { color: "white", bold: true, underline: true }, "INQUIRY RESPONSE"), /* @__PURE__ */ React15.createElement(Text16, { color: "gray" }, "[ ESC to Close ]")), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(CodeRenderer, { text: btwResponse, columns: terminalSize.columns - 6 }))), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, null, statusText ? /* @__PURE__ */ React15.createElement(Box15, { gap: 1 }, /* @__PURE__ */ React15.createElement(dist_default, { colors: ["#001a1a", "#080510", "#12021c"] }, /* @__PURE__ */ React15.createElement(build_default, null)), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true, italic: true }, statusText)) : /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, input.length > 0 && escPressCount ? "Press ESC again to clear input" : hasPasteBlock ? "Press CTRL + O to expand" : "Waiting for input...")), /* @__PURE__ */ React15.createElement(Box15, null, wittyPhrase && /* @__PURE__ */ React15.createElement(Text16, { color: "gray", italic: true }, wittyPhrase, " "), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React15.createElement(Box15, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { width: "100%", height: 1, overflow: "hidden" }, /* @__PURE__ */ React15.createElement(Text16, { color: "#555555" }, "\u2584".repeat(Math.max(1, terminalSize.columns)))), /* @__PURE__ */ React15.createElement(
|
|
17151
17893
|
Box15,
|
|
17152
17894
|
{
|
|
17153
17895
|
backgroundColor: "#555555",
|
|
@@ -17160,6 +17902,7 @@ Selection: ${val}`,
|
|
|
17160
17902
|
MultilineInput,
|
|
17161
17903
|
{
|
|
17162
17904
|
key: `input-${inputKey}`,
|
|
17905
|
+
onPasteStateChange: setHasPasteBlock,
|
|
17163
17906
|
focus: !isTerminalFocused && !isCompressing,
|
|
17164
17907
|
showCursor: isAppFocused && !isCompressing,
|
|
17165
17908
|
lastFocusEventTime: lastFocusEventTime.current,
|
|
@@ -17203,7 +17946,7 @@ Selection: ${val}`,
|
|
|
17203
17946
|
aiProvider,
|
|
17204
17947
|
version: versionFluxflow
|
|
17205
17948
|
}
|
|
17206
|
-
)), activeCommand && /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused, isPty: isActiveCommandPty }))), isInitializing ? /* @__PURE__ */ React15.createElement(Box15, { borderStyle: "double", borderColor: "grey", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, "Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React15.createElement(Box15, { borderStyle: "round", borderColor: "white", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "API KEY REQUIRED")), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, flexDirection: "column" }, setupStep === 0 ? /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, "Select your Preferred Provider:"), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
|
|
17949
|
+
)), activeCommand && /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused, isPty: isActiveCommandPty, terminalHeight: terminalSize.rows }))), isInitializing ? /* @__PURE__ */ React15.createElement(Box15, { borderStyle: "double", borderColor: "grey", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, "Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React15.createElement(Box15, { borderStyle: "round", borderColor: "white", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React15.createElement(Text16, { color: "gray", bold: true }, "API KEY REQUIRED")), /* @__PURE__ */ React15.createElement(Box15, { paddingX: 1, flexDirection: "column" }, setupStep === 0 ? /* @__PURE__ */ React15.createElement(React15.Fragment, null, /* @__PURE__ */ React15.createElement(Text16, { color: "white" }, "Select your Preferred Provider:"), /* @__PURE__ */ React15.createElement(Box15, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
|
|
17207
17950
|
CommandMenu,
|
|
17208
17951
|
{
|
|
17209
17952
|
items: [
|
|
@@ -17573,7 +18316,22 @@ var init_app = __esm({
|
|
|
17573
18316
|
// src/cli.jsx
|
|
17574
18317
|
import { spawn as spawn3 } from "child_process";
|
|
17575
18318
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17576
|
-
|
|
18319
|
+
import os5 from "os";
|
|
18320
|
+
var totalSystemRamBytes = os5.totalmem();
|
|
18321
|
+
var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
|
|
18322
|
+
var SAFETY_MARGIN = 0.5;
|
|
18323
|
+
var calculatedLimit = Math.floor(totalSystemRamMB * SAFETY_MARGIN);
|
|
18324
|
+
var _rawArgs = process.argv.slice(2);
|
|
18325
|
+
var _allocIdx = _rawArgs.indexOf("--allocation");
|
|
18326
|
+
var _allocValue = _allocIdx !== -1 ? parseInt(_rawArgs[_allocIdx + 1], 10) : NaN;
|
|
18327
|
+
var _maxAllowed = Math.floor(totalSystemRamMB * 0.75);
|
|
18328
|
+
var HEAP_LIMIT = !isNaN(_allocValue) && _allocValue > 0 ? Math.min(_allocValue, _maxAllowed) : Math.max(1536, Math.min(32768, calculatedLimit));
|
|
18329
|
+
if (!Number.isNaN(_allocValue)) {
|
|
18330
|
+
console.log("\n[MEMORY] Using custom memory allocation: " + _allocValue + " MB" + (_allocValue > _maxAllowed ? " (Max allowed: " + _maxAllowed + "MB)" : ""));
|
|
18331
|
+
await new Promise((resolve) => setTimeout(resolve, 2e3));
|
|
18332
|
+
} else {
|
|
18333
|
+
console.log("\n[MEMORY] Using auto-detected memory allocation: " + calculatedLimit + " MB");
|
|
18334
|
+
}
|
|
17577
18335
|
var isBundled = fileURLToPath2(import.meta.url).endsWith(".js");
|
|
17578
18336
|
if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-size"))) {
|
|
17579
18337
|
const cp = spawn3(process.execPath, [
|
|
@@ -17608,6 +18366,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
17608
18366
|
--thinking <Fast|Low|Medium|High|xHigh> Set startup thinking level
|
|
17609
18367
|
--memory <on|off> Toggle memory system
|
|
17610
18368
|
--resume <session_id> Resume a previous session
|
|
18369
|
+
--allocation <mb> Override Node.js max-old-space-size in MB (default: auto)
|
|
17611
18370
|
--package <npm|pnpm|yarn|bun> Set package manager for updates
|
|
17612
18371
|
--auto-del <1d|7d|30d> Set history auto-deletion timeframe
|
|
17613
18372
|
--auto-exec <on|off> Toggle permission for autonomous command execution
|
|
@@ -17697,7 +18456,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
17697
18456
|
}
|
|
17698
18457
|
const promptPackageManager = async () => {
|
|
17699
18458
|
const React17 = (await import("react")).default;
|
|
17700
|
-
const { useState:
|
|
18459
|
+
const { useState: useState15 } = React17;
|
|
17701
18460
|
const { render: render2, Box: Box16, Text: Text17 } = await import("ink");
|
|
17702
18461
|
const SelectInput3 = (await import("ink-select-input")).default;
|
|
17703
18462
|
const TextInput5 = (await import("ink-text-input")).default;
|
|
@@ -17714,8 +18473,8 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
17714
18473
|
};
|
|
17715
18474
|
let unmountFn;
|
|
17716
18475
|
const PromptComponent = () => {
|
|
17717
|
-
const [step, setStep] =
|
|
17718
|
-
const [customCommand2, setCustomCommand] =
|
|
18476
|
+
const [step, setStep] = useState15("select");
|
|
18477
|
+
const [customCommand2, setCustomCommand] = useState15("");
|
|
17719
18478
|
const handleSelect = (item) => {
|
|
17720
18479
|
if (item.value === "custom") {
|
|
17721
18480
|
setStep("custom");
|
|
@@ -17816,7 +18575,20 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
17816
18575
|
if (process.stdout.isTTY) {
|
|
17817
18576
|
process.stdout.write("\x1B]0;FluxFlow\x07");
|
|
17818
18577
|
process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow\x07");
|
|
18578
|
+
process.stdout.write("\x1B[?2004h");
|
|
17819
18579
|
}
|
|
18580
|
+
const disableBracketedPaste = () => {
|
|
18581
|
+
if (process.stdout.isTTY) {
|
|
18582
|
+
process.stdout.write("\x1B[?2004l");
|
|
18583
|
+
}
|
|
18584
|
+
};
|
|
18585
|
+
process.on("exit", disableBracketedPaste);
|
|
18586
|
+
["SIGINT", "SIGTERM", "SIGHUP"].forEach((sig) => {
|
|
18587
|
+
process.once(sig, () => {
|
|
18588
|
+
disableBracketedPaste();
|
|
18589
|
+
process.exit(0);
|
|
18590
|
+
});
|
|
18591
|
+
});
|
|
17820
18592
|
if (args.includes("--playground")) {
|
|
17821
18593
|
const originalCwd = process.cwd();
|
|
17822
18594
|
process.argv.push("--original-cwd", originalCwd);
|