fluxflow-cli 1.17.5 → 1.18.1
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 +622 -364
- package/package.json +4 -4
package/dist/fluxflow.js
CHANGED
|
@@ -97,7 +97,7 @@ var init_MultilineInput = __esm({
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
return {
|
|
100
|
-
preCursor: [{ value: " ", type: "cursor" }],
|
|
100
|
+
preCursor: [{ value: showCursor && focus ? "\u2502" : "", type: "cursor" }],
|
|
101
101
|
postCursor: []
|
|
102
102
|
};
|
|
103
103
|
}
|
|
@@ -119,7 +119,7 @@ var init_MultilineInput = __esm({
|
|
|
119
119
|
preCursor: [
|
|
120
120
|
{ value: formattedBefore.slice(0, lineStart) },
|
|
121
121
|
{ value: formattedBefore.slice(lineStart), type: "highlight" },
|
|
122
|
-
{ value: showCursor && focus ? "
|
|
122
|
+
{ value: showCursor && focus ? "\u2502" : "", type: "cursor" }
|
|
123
123
|
],
|
|
124
124
|
postCursor: [
|
|
125
125
|
{ value: formattedAfter.slice(0, lineEnd), type: "highlight" },
|
|
@@ -135,7 +135,7 @@ var init_MultilineInput = __esm({
|
|
|
135
135
|
type: "highlight"
|
|
136
136
|
},
|
|
137
137
|
{ value: formatText(textBefore.slice(highlight.end)) },
|
|
138
|
-
{ value: " ", type: "cursor" }
|
|
138
|
+
{ value: showCursor && focus ? "\u2502" : "", type: "cursor" }
|
|
139
139
|
],
|
|
140
140
|
postCursor: [
|
|
141
141
|
{
|
|
@@ -188,8 +188,10 @@ var init_MultilineInput = __esm({
|
|
|
188
188
|
return highlightStyle ?? textStyle;
|
|
189
189
|
case "cursor":
|
|
190
190
|
return {
|
|
191
|
-
...
|
|
192
|
-
|
|
191
|
+
...textStyle,
|
|
192
|
+
color: "cyan",
|
|
193
|
+
bold: true,
|
|
194
|
+
inverse: false
|
|
193
195
|
};
|
|
194
196
|
default:
|
|
195
197
|
return textStyle;
|
|
@@ -207,6 +209,7 @@ var init_MultilineInput = __esm({
|
|
|
207
209
|
showCursor = true,
|
|
208
210
|
highlightPastedText = false,
|
|
209
211
|
focus = true,
|
|
212
|
+
columns = 80,
|
|
210
213
|
useCustomInput = (inputHandler, isActive) => useInput(inputHandler, { isActive }),
|
|
211
214
|
...controlledProps
|
|
212
215
|
}) => {
|
|
@@ -217,6 +220,49 @@ var init_MultilineInput = __esm({
|
|
|
217
220
|
setCursorIndex(value.length);
|
|
218
221
|
}
|
|
219
222
|
}, [value, cursorIndex]);
|
|
223
|
+
const getVisualPosition = useCallback((index) => {
|
|
224
|
+
const text = normalizeLineEndings(value);
|
|
225
|
+
const lines = text.split("\n");
|
|
226
|
+
const wrapWidth = Math.max(20, columns - 10);
|
|
227
|
+
let visualLine = 0;
|
|
228
|
+
let visualCol = 0;
|
|
229
|
+
let currentIdx = 0;
|
|
230
|
+
for (let i = 0; i < lines.length; i++) {
|
|
231
|
+
const line = lines[i];
|
|
232
|
+
const lineLen = line.length;
|
|
233
|
+
if (index >= currentIdx && index <= currentIdx + lineLen) {
|
|
234
|
+
const offsetInLine = index - currentIdx;
|
|
235
|
+
visualLine += Math.floor(offsetInLine / wrapWidth);
|
|
236
|
+
visualCol = offsetInLine % wrapWidth;
|
|
237
|
+
return { visualLine, visualCol };
|
|
238
|
+
}
|
|
239
|
+
const numVisualLines = Math.max(1, Math.ceil(lineLen / wrapWidth));
|
|
240
|
+
visualLine += numVisualLines;
|
|
241
|
+
currentIdx += lineLen + 1;
|
|
242
|
+
}
|
|
243
|
+
return { visualLine, visualCol };
|
|
244
|
+
}, [value, columns]);
|
|
245
|
+
const getIndexFromVisual = useCallback((targetLine, targetCol) => {
|
|
246
|
+
const text = normalizeLineEndings(value);
|
|
247
|
+
const lines = text.split("\n");
|
|
248
|
+
const wrapWidth = Math.max(20, columns - 10);
|
|
249
|
+
let currentVisualLine = 0;
|
|
250
|
+
let currentIdx = 0;
|
|
251
|
+
for (let i = 0; i < lines.length; i++) {
|
|
252
|
+
const line = lines[i];
|
|
253
|
+
const lineLen = line.length;
|
|
254
|
+
const numVisualLines = Math.max(1, Math.ceil(lineLen / wrapWidth));
|
|
255
|
+
if (targetLine >= currentVisualLine && targetLine < currentVisualLine + numVisualLines) {
|
|
256
|
+
const lineOffset = (targetLine - currentVisualLine) * wrapWidth;
|
|
257
|
+
const colInLine = Math.min(targetCol, lineLen - lineOffset);
|
|
258
|
+
const finalCol = Math.max(0, colInLine);
|
|
259
|
+
return Math.min(currentIdx + lineOffset + finalCol, currentIdx + lineLen);
|
|
260
|
+
}
|
|
261
|
+
currentVisualLine += numVisualLines;
|
|
262
|
+
currentIdx += lineLen + 1;
|
|
263
|
+
}
|
|
264
|
+
return value.length;
|
|
265
|
+
}, [value, columns]);
|
|
220
266
|
useCustomInput((input, key) => {
|
|
221
267
|
const submitKey = keyBindings?.submit ?? ((key2) => key2.return && key2.ctrl);
|
|
222
268
|
const newlineKey = keyBindings?.newline ?? ((key2) => key2.return);
|
|
@@ -233,83 +279,26 @@ var init_MultilineInput = __esm({
|
|
|
233
279
|
if (key.tab || key.shift && key.tab || key.ctrl && input === "c") {
|
|
234
280
|
return;
|
|
235
281
|
}
|
|
236
|
-
if (keyBindings?.newline?.(key)) {
|
|
237
|
-
const newValue = value.slice(0, cursorIndex) + "\n" + value.slice(cursorIndex);
|
|
238
|
-
onChange(newValue);
|
|
239
|
-
setCursorIndex(cursorIndex + 1);
|
|
240
|
-
setPasteLength(0);
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
282
|
let nextPasteLength = 0;
|
|
244
283
|
if (input.length > 1) {
|
|
245
284
|
nextPasteLength = input.length;
|
|
246
285
|
}
|
|
247
286
|
if (key.upArrow) {
|
|
248
287
|
if (showCursor) {
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
const line = lines[i];
|
|
255
|
-
if (line === void 0) continue;
|
|
256
|
-
const lineLen = line.length;
|
|
257
|
-
const lineEnd = currentPos + lineLen;
|
|
258
|
-
if (cursorIndex >= currentPos && cursorIndex <= lineEnd) {
|
|
259
|
-
currentLineIndex = i;
|
|
260
|
-
col = cursorIndex - currentPos;
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
currentPos = lineEnd + 1;
|
|
264
|
-
}
|
|
265
|
-
if (currentLineIndex > 0) {
|
|
266
|
-
const targetLineIndex = currentLineIndex - 1;
|
|
267
|
-
const targetLine = lines[targetLineIndex];
|
|
268
|
-
if (targetLine !== void 0) {
|
|
269
|
-
const targetLineLen = targetLine.length;
|
|
270
|
-
const newCol = Math.min(col, targetLineLen);
|
|
271
|
-
let newIndex = 0;
|
|
272
|
-
for (let i = 0; i < targetLineIndex; i++) {
|
|
273
|
-
newIndex += lines[i].length + 1;
|
|
274
|
-
}
|
|
275
|
-
newIndex += newCol;
|
|
276
|
-
setCursorIndex(newIndex);
|
|
277
|
-
setPasteLength(0);
|
|
278
|
-
}
|
|
288
|
+
const { visualLine, visualCol } = getVisualPosition(cursorIndex);
|
|
289
|
+
if (visualLine > 0) {
|
|
290
|
+
const newIndex = getIndexFromVisual(visualLine - 1, visualCol);
|
|
291
|
+
setCursorIndex(newIndex);
|
|
292
|
+
setPasteLength(0);
|
|
279
293
|
}
|
|
280
294
|
}
|
|
281
295
|
} else if (key.downArrow) {
|
|
282
296
|
if (showCursor) {
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
const line = lines[i];
|
|
289
|
-
if (line === void 0) continue;
|
|
290
|
-
const lineLen = line.length;
|
|
291
|
-
const lineEnd = currentPos + lineLen;
|
|
292
|
-
if (cursorIndex >= currentPos && cursorIndex <= lineEnd) {
|
|
293
|
-
currentLineIndex = i;
|
|
294
|
-
col = cursorIndex - currentPos;
|
|
295
|
-
break;
|
|
296
|
-
}
|
|
297
|
-
currentPos = lineEnd + 1;
|
|
298
|
-
}
|
|
299
|
-
if (currentLineIndex < lines.length - 1) {
|
|
300
|
-
const targetLineIndex = currentLineIndex + 1;
|
|
301
|
-
const targetLine = lines[targetLineIndex];
|
|
302
|
-
if (targetLine !== void 0) {
|
|
303
|
-
const targetLineLen = targetLine.length;
|
|
304
|
-
const newCol = Math.min(col, targetLineLen);
|
|
305
|
-
let newIndex = 0;
|
|
306
|
-
for (let i = 0; i < targetLineIndex; i++) {
|
|
307
|
-
newIndex += lines[i].length + 1;
|
|
308
|
-
}
|
|
309
|
-
newIndex += newCol;
|
|
310
|
-
setCursorIndex(newIndex);
|
|
311
|
-
setPasteLength(0);
|
|
312
|
-
}
|
|
297
|
+
const { visualLine, visualCol } = getVisualPosition(cursorIndex);
|
|
298
|
+
const newIndex = getIndexFromVisual(visualLine + 1, visualCol);
|
|
299
|
+
if (newIndex !== cursorIndex) {
|
|
300
|
+
setCursorIndex(newIndex);
|
|
301
|
+
setPasteLength(0);
|
|
313
302
|
}
|
|
314
303
|
}
|
|
315
304
|
} else if (key.leftArrow) {
|
|
@@ -374,66 +363,53 @@ var init_text = __esm({
|
|
|
374
363
|
"src/utils/text.js"() {
|
|
375
364
|
wrapText = (text, width) => {
|
|
376
365
|
if (!text) return "";
|
|
377
|
-
const
|
|
366
|
+
const ansiRegex = /\x1B\[[0-?]*[ -/]*[@-~]/g;
|
|
367
|
+
const sourceLines = text.split("\n");
|
|
378
368
|
let finalLines = [];
|
|
379
369
|
if (width <= 5) return text;
|
|
370
|
+
const getVisibleLength = (str) => str.replace(ansiRegex, "").length;
|
|
380
371
|
sourceLines.forEach((sLine) => {
|
|
381
|
-
|
|
372
|
+
const visibleLength = getVisibleLength(sLine);
|
|
373
|
+
if (visibleLength <= width) {
|
|
382
374
|
finalLines.push(sLine);
|
|
383
375
|
return;
|
|
384
376
|
}
|
|
385
377
|
const tokens = sLine.split(/(\s+)/);
|
|
386
378
|
let currentLine = "";
|
|
387
|
-
let
|
|
388
|
-
let lastSignificantGap = 0;
|
|
379
|
+
let currentVisibleLength = 0;
|
|
389
380
|
const leadingSpaceMatch = sLine.match(/^(\s*)/);
|
|
390
|
-
|
|
391
|
-
lastSignificantGap = leadingSpaceMatch[1].length;
|
|
392
|
-
}
|
|
393
|
-
const listMatch = sLine.match(/^\s*([-*]|\d+\.)\s+/);
|
|
394
|
-
if (listMatch) {
|
|
395
|
-
lastSignificantGap = listMatch[0].length;
|
|
396
|
-
}
|
|
381
|
+
const indent = leadingSpaceMatch ? leadingSpaceMatch[1] : "";
|
|
397
382
|
tokens.forEach((token, idx) => {
|
|
398
383
|
if (token.length === 0) return;
|
|
399
|
-
const
|
|
400
|
-
if (
|
|
401
|
-
if (
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
lastSignificantGap = originalXPos + pipeIdx + 1;
|
|
411
|
-
}
|
|
412
|
-
if ((currentLine + token).length > width) {
|
|
413
|
-
if (currentLine.trim().length > 0) {
|
|
414
|
-
finalLines.push(currentLine.replace(/\s+$/, ""));
|
|
415
|
-
const safeIndent = Math.min(lastSignificantGap, Math.max(0, width - 12));
|
|
416
|
-
const indent = " ".repeat(safeIndent);
|
|
417
|
-
currentLine = indent + token;
|
|
418
|
-
while (currentLine.length > width && width > 20) {
|
|
419
|
-
finalLines.push(currentLine.substring(0, width));
|
|
420
|
-
currentLine = indent + currentLine.substring(width);
|
|
421
|
-
}
|
|
384
|
+
const tokenVisibleLength = getVisibleLength(token);
|
|
385
|
+
if (currentVisibleLength + tokenVisibleLength > width) {
|
|
386
|
+
if (currentLine.trim().length > 0) {
|
|
387
|
+
finalLines.push(currentLine.trimEnd());
|
|
388
|
+
currentLine = indent + token;
|
|
389
|
+
currentVisibleLength = getVisibleLength(currentLine);
|
|
390
|
+
} else {
|
|
391
|
+
if (ansiRegex.test(token)) {
|
|
392
|
+
finalLines.push(token);
|
|
393
|
+
currentLine = indent;
|
|
394
|
+
currentVisibleLength = getVisibleLength(currentLine);
|
|
422
395
|
} else {
|
|
423
396
|
let word = token;
|
|
424
|
-
while (word
|
|
397
|
+
while (getVisibleLength(word) > width && width > 10) {
|
|
425
398
|
finalLines.push(word.substring(0, width));
|
|
426
399
|
word = word.substring(width);
|
|
427
400
|
}
|
|
428
401
|
currentLine = word;
|
|
402
|
+
currentVisibleLength = getVisibleLength(currentLine);
|
|
429
403
|
}
|
|
430
|
-
} else {
|
|
431
|
-
currentLine += token;
|
|
432
404
|
}
|
|
405
|
+
} else {
|
|
406
|
+
currentLine += token;
|
|
407
|
+
currentVisibleLength += tokenVisibleLength;
|
|
433
408
|
}
|
|
434
|
-
originalXPos += token.length;
|
|
435
409
|
});
|
|
436
|
-
if (currentLine
|
|
410
|
+
if (currentLine.trimEnd().length > 0 || currentLine === indent) {
|
|
411
|
+
finalLines.push(currentLine.trimEnd());
|
|
412
|
+
}
|
|
437
413
|
});
|
|
438
414
|
return finalLines.join("\n");
|
|
439
415
|
};
|
|
@@ -463,10 +439,14 @@ var TerminalBox;
|
|
|
463
439
|
var init_TerminalBox = __esm({
|
|
464
440
|
"src/components/TerminalBox.jsx"() {
|
|
465
441
|
init_text();
|
|
466
|
-
TerminalBox = React2.memo(({ command, output, completed = false, isFocused = false, columns = 80 }) => {
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
442
|
+
TerminalBox = React2.memo(({ command, output, completed = false, isFocused = false, columns = 80, isPty = false }) => {
|
|
443
|
+
const processOutput = (text) => {
|
|
444
|
+
if (!text) return "";
|
|
445
|
+
return text.split(/\r\n|\r|\n/).map((line) => line.trimEnd()).join("\n").replace(/^\n+|\n+$/g, "");
|
|
446
|
+
};
|
|
447
|
+
const cleanOutput = processOutput(output);
|
|
448
|
+
const displayOutput = isPty ? cleanOutput : cleanOutput ? wrapText(cleanOutput, columns - 6) : "";
|
|
449
|
+
return /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: isFocused ? "double" : "round", borderColor: completed ? "#334155" : isFocused ? "yellow" : "cyan", paddingX: 2, paddingY: completed ? 0 : 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexShrink: 1, paddingRight: 2 }, /* @__PURE__ */ React2.createElement(Text2, null, /* @__PURE__ */ React2.createElement(Text2, { color: completed ? "gray" : isFocused ? "yellow" : "cyan", bold: true }, completed ? "\u{1F3C1} FINISHED:" : "\u26A1 EXECUTING:", " "), /* @__PURE__ */ React2.createElement(Text2, { color: completed ? "gray" : "white" }, command))), isPty && /* @__PURE__ */ React2.createElement(Box2, { flexShrink: 0, paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: completed ? "gray" : "magenta", bold: true }, "ADVANCE"))), displayOutput ? /* @__PURE__ */ React2.createElement(Box2, { marginTop: completed ? 0 : 1, backgroundColor: isPty ? void 0 : "#0a0a0a", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: completed ? "gray" : void 0 }, displayOutput)) : !completed && /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1, backgroundColor: isPty ? void 0 : "#0a0a0a", paddingX: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "gray", italic: true }, "Waiting for output...")), /* @__PURE__ */ React2.createElement(Box2, { justifyContent: "space-between", marginTop: 1 }, !completed ? /* @__PURE__ */ React2.createElement(Text2, { color: "gray", dimColor: true, italic: true }, "Double-press ESC to terminate if hanging.") : /* @__PURE__ */ React2.createElement(Box2, null), /* @__PURE__ */ React2.createElement(Text2, { color: completed ? "#475569" : isFocused ? "yellow" : "cyan", bold: true }, completed ? "\u25CF ARCHIVED" : isFocused ? "\u25B6 TERMINAL FOCUSED" : "\u25CF LIVE (Press TAB to focus)")));
|
|
470
450
|
});
|
|
471
451
|
}
|
|
472
452
|
});
|
|
@@ -510,7 +490,7 @@ var init_ChatLayout = __esm({
|
|
|
510
490
|
"exec_command": "ExecuteCommand",
|
|
511
491
|
"web_search": "WebSearch",
|
|
512
492
|
"web_scrape": "ReadSite",
|
|
513
|
-
"search_keyword": "
|
|
493
|
+
"search_keyword": "SearchKeyword",
|
|
514
494
|
"write_pdf": "CreatePDF",
|
|
515
495
|
"write_docx": "CreateDocument",
|
|
516
496
|
"generate_image": "GenerateImage",
|
|
@@ -744,20 +724,26 @@ var init_ChatLayout = __esm({
|
|
|
744
724
|
DiffLine = React3.memo(({ line, columns = 80 }) => {
|
|
745
725
|
const isContext = line.includes("[UI_CONTEXT]");
|
|
746
726
|
const cleanLine = line.replace("[UI_CONTEXT]", "");
|
|
727
|
+
if (isContext && cleanLine.includes("\u2550")) {
|
|
728
|
+
return /* @__PURE__ */ React3.createElement(Box3, { backgroundColor: "#1a1a1a", paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, "\u2550".repeat(Math.max(10, columns - 4))));
|
|
729
|
+
}
|
|
747
730
|
const isRemoval = cleanLine.startsWith("-");
|
|
748
731
|
const isAddition = cleanLine.startsWith("+");
|
|
749
|
-
const
|
|
750
|
-
const
|
|
751
|
-
const
|
|
732
|
+
const prefixChar = cleanLine[0];
|
|
733
|
+
const rest = cleanLine.substring(1);
|
|
734
|
+
const splitIdx = rest.indexOf("|");
|
|
735
|
+
const lineNum = splitIdx !== -1 ? rest.substring(0, splitIdx).trim() : "";
|
|
736
|
+
const content = splitIdx !== -1 ? rest.substring(splitIdx + 1) : rest;
|
|
752
737
|
const bgColor = isRemoval ? "#3a0c0c" : isAddition ? "#0c3a1a" : "#1a1a1a";
|
|
753
|
-
const textColor = isRemoval ? "#ff4d4d" : isAddition ? "#4dff88" : "white";
|
|
754
|
-
|
|
738
|
+
const textColor = isRemoval ? "#ff4d4d" : isAddition ? "#4dff88" : isContext ? "gray" : "white";
|
|
739
|
+
const numColor = isRemoval ? "#cf3a3a" : isAddition ? "#3acf65" : "gray";
|
|
740
|
+
return /* @__PURE__ */ React3.createElement(Box3, { backgroundColor: bgColor, paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(Box3, { width: 5, flexShrink: 0 }, /* @__PURE__ */ React3.createElement(Text3, { color: numColor, dimColor: isContext }, lineNum)), /* @__PURE__ */ React3.createElement(Box3, { width: 2, flexShrink: 0, marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: textColor, bold: true }, isRemoval ? "-" : isAddition ? "+" : " ")), /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: textColor, dimColor: isContext }, wrapText(content, columns - 14))));
|
|
755
741
|
});
|
|
756
742
|
DiffBlock = React3.memo(({ text, columns = 80 }) => {
|
|
757
743
|
const match = text.match(/\[DIFF_START\]([\s\S]*?)\[DIFF_END\]/);
|
|
758
744
|
const diffBody = match ? match[1].trim() : "";
|
|
759
745
|
const diffLines = diffBody.split("\n");
|
|
760
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width:
|
|
746
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width: columns - 3, marginBottom: 0 }, /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", backgroundColor: "#1a1a1a", paddingY: 0, width: "100%" }, diffLines.map((line, i) => /* @__PURE__ */ React3.createElement(DiffLine, { key: i, line, columns: columns - 3 }))));
|
|
761
747
|
});
|
|
762
748
|
CodeRenderer = React3.memo(({ text, columns = 80 }) => {
|
|
763
749
|
if (!text) return null;
|
|
@@ -774,11 +760,11 @@ var init_ChatLayout = __esm({
|
|
|
774
760
|
const footer = contentAndFooter[1] ? `${footerMarker}${contentAndFooter[1]}` : "";
|
|
775
761
|
const codeLines = content.split("\n");
|
|
776
762
|
const gutterWidth = String(codeLines.length).length;
|
|
777
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width:
|
|
763
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width: columns - 3 }, /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "#444", paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(Box3, { alignSelf: "flex-end", marginTop: -1, marginRight: 1 }, /* @__PURE__ */ React3.createElement(Text3, { backgroundColor: "#444", color: "white" }, " FILE SNAPSHOT ")), /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", paddingY: 1, width: "100%" }, codeLines.map((line, idx) => /* @__PURE__ */ React3.createElement(Box3, { key: idx, width: "100%" }, /* @__PURE__ */ React3.createElement(Box3, { width: gutterWidth + 2, flexShrink: 0 }, /* @__PURE__ */ React3.createElement(Text3, { color: "gray", dimColor: true }, String(idx + 1).padStart(gutterWidth, " "), " ")), /* @__PURE__ */ React3.createElement(Box3, { flexGrow: 1 }, /* @__PURE__ */ React3.createElement(Text3, { color: "white" }, line)))))));
|
|
778
764
|
}
|
|
779
765
|
if (text.includes("```")) {
|
|
780
766
|
const parts = text.split(/(```\w*\n?[\s\S]*?(?:```|$))/g);
|
|
781
|
-
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width:
|
|
767
|
+
return /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", width: columns - 3 }, parts.map((part, i) => {
|
|
782
768
|
if (part.startsWith("```")) {
|
|
783
769
|
const match = part.match(/```(\w*)\n?([\s\S]*?)(?:```|$)/);
|
|
784
770
|
const lang = match ? match[1] : "code";
|
|
@@ -795,10 +781,10 @@ var init_ChatLayout = __esm({
|
|
|
795
781
|
cleanPart = cleanPart.replace(/[\r\n]+$/, "");
|
|
796
782
|
}
|
|
797
783
|
if (!cleanPart) return null;
|
|
798
|
-
return /* @__PURE__ */ React3.createElement(MarkdownText, { key: i, text: cleanPart, columns });
|
|
784
|
+
return /* @__PURE__ */ React3.createElement(MarkdownText, { key: i, text: cleanPart, columns: columns - 3 });
|
|
799
785
|
}));
|
|
800
786
|
}
|
|
801
|
-
return /* @__PURE__ */ React3.createElement(MarkdownText, { text, columns });
|
|
787
|
+
return /* @__PURE__ */ React3.createElement(MarkdownText, { text, columns: columns - 3 });
|
|
802
788
|
});
|
|
803
789
|
formatThinkingDuration = (ms) => {
|
|
804
790
|
const totalSecs = Math.round(ms / 1e3);
|
|
@@ -876,12 +862,14 @@ var init_ChatLayout = __esm({
|
|
|
876
862
|
];
|
|
877
863
|
return /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(Text3, { color: "magenta", bold: true, underline: true }, "\u{1F4DC} COMMAND REFERENCE"), /* @__PURE__ */ React3.createElement(Box3, { flexDirection: "column", marginTop: 1 }, commandList.map((c, i) => /* @__PURE__ */ React3.createElement(Box3, { key: i, flexDirection: "row" }, /* @__PURE__ */ React3.createElement(Box3, { width: 15 }, /* @__PURE__ */ React3.createElement(Text3, { color: "cyan", bold: true }, c.cmd)), /* @__PURE__ */ React3.createElement(Text3, { color: "gray" }, " - ", c.desc))))));
|
|
878
864
|
}
|
|
879
|
-
if (isTerminalRecord) {
|
|
880
|
-
const cmdMatch = msg.text.match(/COMMAND: (.*)
|
|
881
|
-
const
|
|
865
|
+
if (msg.isTerminalRecord) {
|
|
866
|
+
const cmdMatch = msg.text.match(/COMMAND: (.*)/);
|
|
867
|
+
const ptyMatch = msg.text.match(/PTY: (true|false)/);
|
|
868
|
+
const outputMatch = msg.text.match(/OUTPUT: ([\s\S]*)/);
|
|
882
869
|
const cmd = cmdMatch ? cmdMatch[1] : "Unknown";
|
|
870
|
+
const isPty = ptyMatch ? ptyMatch[1] === "true" : false;
|
|
883
871
|
const outputList = outputMatch ? outputMatch[1] : "";
|
|
884
|
-
return /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(TerminalBox, { command: cmd, output: outputList, completed: true, columns }));
|
|
872
|
+
return /* @__PURE__ */ React3.createElement(Box3, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React3.createElement(TerminalBox, { command: cmd, output: outputList, completed: true, columns, isPty }));
|
|
885
873
|
}
|
|
886
874
|
const [animationDone, setAnimationDone] = React3.useState(!msg.isStreaming);
|
|
887
875
|
const content = React3.useMemo(() => cleanSignals(msg.text), [msg.text]);
|
|
@@ -1648,9 +1636,22 @@ var init_secrets = __esm({
|
|
|
1648
1636
|
});
|
|
1649
1637
|
|
|
1650
1638
|
// src/data/main_tools.js
|
|
1651
|
-
|
|
1639
|
+
import { execSync } from "child_process";
|
|
1640
|
+
var _isPsAvailable, isPsAvailable, TOOL_PROTOCOL;
|
|
1652
1641
|
var init_main_tools = __esm({
|
|
1653
1642
|
"src/data/main_tools.js"() {
|
|
1643
|
+
_isPsAvailable = null;
|
|
1644
|
+
isPsAvailable = () => {
|
|
1645
|
+
if (process.platform !== "win32") return false;
|
|
1646
|
+
if (_isPsAvailable !== null) return _isPsAvailable;
|
|
1647
|
+
try {
|
|
1648
|
+
execSync('powershell.exe -NoProfile -Command "exit"', { stdio: "ignore" });
|
|
1649
|
+
_isPsAvailable = true;
|
|
1650
|
+
} catch (e) {
|
|
1651
|
+
_isPsAvailable = false;
|
|
1652
|
+
}
|
|
1653
|
+
return _isPsAvailable;
|
|
1654
|
+
};
|
|
1654
1655
|
TOOL_PROTOCOL = (mode, osDetected) => `
|
|
1655
1656
|
-- TOOL DEFINITIONS --
|
|
1656
1657
|
Access to internal tools. To call a tool, MUST use the exact syntax on a new line: [tool:functions.ToolName(args)]
|
|
@@ -1668,10 +1669,10 @@ Suggest best options; don't ask for preferences
|
|
|
1668
1669
|
${mode === "Flux" ? `- PROJECT TOOLS (path = relative to CWD) -
|
|
1669
1670
|
1. [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. Supports images/docs. User gives image/doc: VIEW FIRST
|
|
1670
1671
|
2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
|
|
1671
|
-
3. [tool:functions.PatchFile(path="...",
|
|
1672
|
+
3. [tool:functions.PatchFile(path="...", replaceContent1="exact string", newContent1="...", ...MAX 8)]. Surgical Patch. Unsure? ReadFile > guessing. Multiple blocks same file? Use replaceContent2, newContent2 etc.
|
|
1672
1673
|
4. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile >> WriteFile. Verify Imports
|
|
1673
|
-
5. [tool:functions.SearchKeyword(keyword="...")]. Global project search. Finds definitions/logic without reading every file
|
|
1674
|
-
6. [tool:functions.Run(command="...")]. Runs a ${osDetected === "Windows" ? "Windows CMD" : "Bash"} command. Destructive/Irreversible ops -> Ask user
|
|
1674
|
+
5. [tool:functions.SearchKeyword(keyword="...", file="path/to/file")]. Global project search. If 'file' is provided, searches only that file. Finds definitions/logic without reading every file
|
|
1675
|
+
6. [tool:functions.Run(command="...")]. Runs a ${osDetected === "Windows" ? isPsAvailable() ? "Windows Powershell" : "Windows CMD" : "Bash"} command. Destructive/Irreversible ops -> Ask user
|
|
1675
1676
|
7. [tool:functions.GenerateImage(path="... png", prompt="detailed", ratio="16:9, 9:16, 1:1")]. Usage: Mockups, PDF thumbnails, any visual content
|
|
1676
1677
|
8. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout (100vh/vw)
|
|
1677
1678
|
9. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document
|
|
@@ -3223,14 +3224,24 @@ var init_update_file = __esm({
|
|
|
3223
3224
|
update_file = async (args) => {
|
|
3224
3225
|
const parsed = parseArgs(args);
|
|
3225
3226
|
const targetPath = parsed.path;
|
|
3226
|
-
let content_to_replace = parsed.content_to_replace !== void 0 ? parsed.content_to_replace : parsed.replaceContent;
|
|
3227
|
-
let content_to_add = parsed.content_to_add !== void 0 ? parsed.content_to_add : parsed.newContent;
|
|
3228
3227
|
if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
|
|
3229
|
-
|
|
3230
|
-
|
|
3228
|
+
const patchPairs = [];
|
|
3229
|
+
const legacyReplace = parsed.content_to_replace !== void 0 ? parsed.content_to_replace : parsed.replaceContent;
|
|
3230
|
+
const legacyNew = parsed.content_to_add !== void 0 ? parsed.content_to_add : parsed.newContent;
|
|
3231
|
+
if (legacyReplace !== void 0 && legacyNew !== void 0) {
|
|
3232
|
+
patchPairs.push({ replace: legacyReplace, new: legacyNew });
|
|
3233
|
+
}
|
|
3234
|
+
for (let i = 1; i <= 10; i++) {
|
|
3235
|
+
const r = parsed[`replaceContent${i}`];
|
|
3236
|
+
const n = parsed[`newContent${i}`];
|
|
3237
|
+
if (r !== void 0 && n !== void 0 && r !== legacyReplace) {
|
|
3238
|
+
patchPairs.push({ replace: r, new: n });
|
|
3239
|
+
}
|
|
3240
|
+
}
|
|
3241
|
+
if (patchPairs.length === 0) {
|
|
3242
|
+
return "ERROR: No valid replacement pairs found. Use replaceContent1, newContent1, etc.";
|
|
3243
|
+
}
|
|
3231
3244
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3232
|
-
content_to_replace = strip(content_to_replace);
|
|
3233
|
-
content_to_add = strip(content_to_add);
|
|
3234
3245
|
const absolutePath = path9.resolve(process.cwd(), targetPath);
|
|
3235
3246
|
try {
|
|
3236
3247
|
if (!fs10.existsSync(absolutePath)) {
|
|
@@ -3238,122 +3249,164 @@ var init_update_file = __esm({
|
|
|
3238
3249
|
}
|
|
3239
3250
|
await RevertManager.recordFileChange(absolutePath);
|
|
3240
3251
|
let diskContent = fs10.readFileSync(absolutePath, "utf8");
|
|
3241
|
-
if (diskContent.startsWith("\uFEFF"))
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3252
|
+
if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
|
|
3253
|
+
let currentFileContent = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3254
|
+
const results = [];
|
|
3255
|
+
let totalInstances = 0;
|
|
3256
|
+
for (let i = 0; i < patchPairs.length; i++) {
|
|
3257
|
+
const pair = patchPairs[i];
|
|
3258
|
+
const content_to_replace = strip(pair.replace);
|
|
3259
|
+
const content_to_add = strip(pair.new);
|
|
3260
|
+
const adjustIndentation = (newText, originalMatch, leadingContext2 = "") => {
|
|
3261
|
+
if (!newText || originalMatch === void 0) return newText;
|
|
3262
|
+
const getIndent = (line) => line.match(/^\s*/)[0];
|
|
3263
|
+
const getMinIndent = (text) => {
|
|
3264
|
+
const lines = text.split("\n").filter((l) => l.trim() !== "");
|
|
3265
|
+
if (lines.length === 0) return "";
|
|
3266
|
+
let min = getIndent(lines[0]);
|
|
3267
|
+
for (const line of lines) {
|
|
3268
|
+
const indent = getIndent(line);
|
|
3269
|
+
if (indent.length < min.length) min = indent;
|
|
3270
|
+
}
|
|
3271
|
+
return min;
|
|
3272
|
+
};
|
|
3273
|
+
const matchBaseIndent = getMinIndent(originalMatch);
|
|
3274
|
+
const targetBaseIndent = leadingContext2.match(/^\s*/)[0] + matchBaseIndent;
|
|
3275
|
+
const newBaseIndent = getMinIndent(newText);
|
|
3276
|
+
const delta = targetBaseIndent.length - newBaseIndent.length;
|
|
3277
|
+
const indentChar = (targetBaseIndent.match(/\s/) || originalMatch.match(/\s/) || [" "])[0];
|
|
3278
|
+
const newLines = newText.split("\n");
|
|
3279
|
+
return newLines.map((line, i2) => {
|
|
3280
|
+
if (line.trim() === "" && i2 !== 0) return "";
|
|
3281
|
+
const currentLineIndent = getIndent(line).length;
|
|
3282
|
+
const shiftedIndentLength = Math.max(0, currentLineIndent + delta);
|
|
3283
|
+
const prependedIndentLength = i2 === 0 ? Math.max(0, shiftedIndentLength - leadingContext2.length) : shiftedIndentLength;
|
|
3284
|
+
return indentChar.repeat(prependedIndentLength) + line.trimStart();
|
|
3285
|
+
}).join("\n");
|
|
3262
3286
|
};
|
|
3263
|
-
const
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
let instances = 0;
|
|
3278
|
-
let startPos = -1;
|
|
3279
|
-
let matchRegex = null;
|
|
3280
|
-
const exactPattern = content_to_replace.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3281
|
-
if (content_to_replace !== "" && currentContent.includes(content_to_replace)) {
|
|
3282
|
-
matchRegex = new RegExp(exactPattern, "g");
|
|
3283
|
-
} else {
|
|
3284
|
-
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*"));
|
|
3285
|
-
if (fuzzyLines.length > 0) {
|
|
3286
|
-
const fuzzyPattern = fuzzyLines.join("\\s*");
|
|
3287
|
-
try {
|
|
3288
|
-
matchRegex = new RegExp(fuzzyPattern, "g");
|
|
3289
|
-
} catch (e) {
|
|
3287
|
+
const exactPattern = content_to_replace.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
3288
|
+
let matchRegex = null;
|
|
3289
|
+
if (content_to_replace !== "" && currentFileContent.includes(content_to_replace)) {
|
|
3290
|
+
matchRegex = new RegExp(exactPattern, "g");
|
|
3291
|
+
} else {
|
|
3292
|
+
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*"));
|
|
3293
|
+
if (fuzzyLines.length > 0) {
|
|
3294
|
+
const fuzzyPattern = fuzzyLines.join("\\s*");
|
|
3295
|
+
try {
|
|
3296
|
+
matchRegex = new RegExp(fuzzyPattern, "g");
|
|
3297
|
+
} catch (e) {
|
|
3298
|
+
matchRegex = new RegExp(exactPattern, "g");
|
|
3299
|
+
}
|
|
3300
|
+
} else {
|
|
3290
3301
|
matchRegex = new RegExp(exactPattern, "g");
|
|
3291
3302
|
}
|
|
3292
|
-
} else {
|
|
3293
|
-
matchRegex = new RegExp(exactPattern, "g");
|
|
3294
3303
|
}
|
|
3304
|
+
const matches = [...currentFileContent.matchAll(matchRegex)];
|
|
3305
|
+
if (matches.length === 0) {
|
|
3306
|
+
results.push({ success: false, error: `Block ${i + 1}: Could not find match.` });
|
|
3307
|
+
continue;
|
|
3308
|
+
}
|
|
3309
|
+
if (matches.length > 1) {
|
|
3310
|
+
results.push({ success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique).` });
|
|
3311
|
+
continue;
|
|
3312
|
+
}
|
|
3313
|
+
const startPos = matches[0].index;
|
|
3314
|
+
const firstMatchContent = matches[0][0];
|
|
3315
|
+
const lineStart = currentFileContent.lastIndexOf("\n", startPos) + 1;
|
|
3316
|
+
const leadingContext = currentFileContent.substring(lineStart, startPos);
|
|
3317
|
+
const finalReplacement = adjustIndentation(content_to_add, firstMatchContent, leadingContext);
|
|
3318
|
+
const allOriginalLines = currentFileContent.split("\n");
|
|
3319
|
+
const patchStartLine = currentFileContent.substring(0, startPos).split("\n").length;
|
|
3320
|
+
const patchOldLines = firstMatchContent.split("\n");
|
|
3321
|
+
const contextBefore = [];
|
|
3322
|
+
for (let j = Math.max(0, patchStartLine - 4); j < patchStartLine - 1; j++) {
|
|
3323
|
+
contextBefore.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3324
|
+
}
|
|
3325
|
+
const contextAfter = [];
|
|
3326
|
+
const patchEndLineIdx = patchStartLine + patchOldLines.length - 1;
|
|
3327
|
+
for (let j = patchEndLineIdx; j < Math.min(allOriginalLines.length, patchEndLineIdx + 3); j++) {
|
|
3328
|
+
contextAfter.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3329
|
+
}
|
|
3330
|
+
results.push({
|
|
3331
|
+
success: true,
|
|
3332
|
+
startPos,
|
|
3333
|
+
oldContent: firstMatchContent,
|
|
3334
|
+
newContent: finalReplacement,
|
|
3335
|
+
originalStartLine: patchStartLine,
|
|
3336
|
+
contextBefore,
|
|
3337
|
+
contextAfter
|
|
3338
|
+
});
|
|
3339
|
+
currentFileContent = currentFileContent.substring(0, startPos) + finalReplacement + currentFileContent.substring(startPos + firstMatchContent.length);
|
|
3340
|
+
totalInstances++;
|
|
3295
3341
|
}
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
return `ERROR: Could not find match for "content_to_replace" in [${targetPath}]. Check for whitespace discrepancies or ReadFile to get exact content.`;
|
|
3300
|
-
}
|
|
3301
|
-
if (instances > 1) {
|
|
3302
|
-
return `ERROR: Unable to find unique match. [${instances}] instances of the specified "content_to_replace" were found in [${targetPath}]. Try providing more context (surrounding lines) to make the match unique.`;
|
|
3342
|
+
if (totalInstances === 0) {
|
|
3343
|
+
return `ERROR: Failed to apply any patches to [${targetPath}].
|
|
3344
|
+
${results.map((r) => r.error).join("\n")}`;
|
|
3303
3345
|
}
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
const newFileContent = currentContent.replace(matchRegex, (match, offset) => {
|
|
3307
|
-
const lineStart = currentContent.lastIndexOf("\n", offset) + 1;
|
|
3308
|
-
const leadingContext = currentContent.substring(lineStart, offset);
|
|
3309
|
-
return adjustIndentation(content_to_add, match, leadingContext);
|
|
3310
|
-
});
|
|
3311
|
-
const firstLineStart = currentContent.lastIndexOf("\n", startPos) + 1;
|
|
3312
|
-
const firstLeadingContext = currentContent.substring(firstLineStart, startPos);
|
|
3313
|
-
const finalContentToAdd = adjustIndentation(content_to_add, firstMatchContent, firstLeadingContext);
|
|
3314
|
-
const finalContentToReplace = firstMatchContent;
|
|
3315
|
-
fs10.writeFileSync(absolutePath, newFileContent, "utf8");
|
|
3316
|
-
const allOriginalLines = currentContent.split(/\r?\n/);
|
|
3317
|
-
const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
|
|
3318
|
-
const oldLines = content_to_replace.split(/\r?\n/);
|
|
3319
|
-
const endLine = startLine + oldLines.length - 1;
|
|
3320
|
-
let diffText = `SUCCESS: File [${targetPath}] updated. [${instances}] instances replaced.
|
|
3346
|
+
fs10.writeFileSync(absolutePath, currentFileContent, "utf8");
|
|
3347
|
+
let diffText = `SUCCESS: File [${targetPath}] updated. [${totalInstances}/${patchPairs.length}] blocks applied.
|
|
3321
3348
|
|
|
3322
3349
|
`;
|
|
3323
3350
|
diffText += `[DIFF_START]
|
|
3324
3351
|
`;
|
|
3325
|
-
const
|
|
3326
|
-
|
|
3327
|
-
|
|
3352
|
+
const terminalWidth = process.stdout.columns || 100;
|
|
3353
|
+
const separatorLine = "\u2550".repeat(Math.max(20, terminalWidth - 12));
|
|
3354
|
+
const allLinesFinal = currentFileContent.split("\n");
|
|
3355
|
+
const successfulPatches = results.filter((r) => r.success);
|
|
3356
|
+
successfulPatches.forEach((res, idx) => {
|
|
3357
|
+
if (idx === 0) {
|
|
3358
|
+
res.contextBefore.forEach((ctx) => {
|
|
3359
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3328
3360
|
`;
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
const fullNewLines = newFileContent.substring(lineStartPos, actualNewEndPos).split("\n");
|
|
3339
|
-
fullOldLines.forEach((line, i) => {
|
|
3340
|
-
diffText += `-${startLine + i}|${line}
|
|
3361
|
+
});
|
|
3362
|
+
} else {
|
|
3363
|
+
const prev = successfulPatches[idx - 1];
|
|
3364
|
+
const prevLinesCount = prev.newContent.split("\n").length;
|
|
3365
|
+
const prevEndLine = prev.originalStartLine + prevLinesCount - 1;
|
|
3366
|
+
const gap = res.originalStartLine - prevEndLine - 1;
|
|
3367
|
+
if (gap >= 1 && gap < 12) {
|
|
3368
|
+
for (let j = prevEndLine; j < res.originalStartLine - 1; j++) {
|
|
3369
|
+
diffText += `[UI_CONTEXT] ${j + 1} |${allLinesFinal[j]}
|
|
3341
3370
|
`;
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3371
|
+
}
|
|
3372
|
+
} else if (gap >= 12) {
|
|
3373
|
+
prev.contextAfter.forEach((ctx) => {
|
|
3374
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3346
3375
|
`;
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
const linesAffected = fullOldLines.length;
|
|
3350
|
-
const originalContextIdx = startLine + linesAffected - 1;
|
|
3351
|
-
for (let i = originalContextIdx; i < Math.min(allOriginalLines.length, originalContextIdx + 15); i++) {
|
|
3352
|
-
diffText += `[UI_CONTEXT] ${currentNewLine}|${allOriginalLines[i]}
|
|
3376
|
+
});
|
|
3377
|
+
diffText += `[UI_CONTEXT] ${separatorLine}
|
|
3353
3378
|
`;
|
|
3354
|
-
|
|
3355
|
-
|
|
3379
|
+
res.contextBefore.forEach((ctx) => {
|
|
3380
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3381
|
+
`;
|
|
3382
|
+
});
|
|
3383
|
+
}
|
|
3384
|
+
}
|
|
3385
|
+
const oldLines = res.oldContent.split("\n");
|
|
3386
|
+
const newLines = res.newContent.split("\n");
|
|
3387
|
+
oldLines.forEach((line, i) => {
|
|
3388
|
+
diffText += `-${res.originalStartLine + i}|${line}
|
|
3389
|
+
`;
|
|
3390
|
+
});
|
|
3391
|
+
newLines.forEach((line, i) => {
|
|
3392
|
+
diffText += `+${res.originalStartLine + i}|${line}
|
|
3393
|
+
`;
|
|
3394
|
+
});
|
|
3395
|
+
if (idx === successfulPatches.length - 1) {
|
|
3396
|
+
res.contextAfter.forEach((ctx) => {
|
|
3397
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3398
|
+
`;
|
|
3399
|
+
});
|
|
3400
|
+
}
|
|
3401
|
+
});
|
|
3356
3402
|
diffText += `[DIFF_END]`;
|
|
3403
|
+
const errors = results.filter((r) => !r.success);
|
|
3404
|
+
if (errors.length > 0) {
|
|
3405
|
+
diffText += `
|
|
3406
|
+
|
|
3407
|
+
\u26A0\uFE0F WARNING: Some blocks failed:
|
|
3408
|
+
${errors.map((e) => ` \u2022 ${e.error}`).join("\n")}`;
|
|
3409
|
+
}
|
|
3357
3410
|
return diffText;
|
|
3358
3411
|
} catch (err) {
|
|
3359
3412
|
return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
|
|
@@ -3364,15 +3417,26 @@ var init_update_file = __esm({
|
|
|
3364
3417
|
|
|
3365
3418
|
// src/tools/exec_command.js
|
|
3366
3419
|
import { spawn } from "child_process";
|
|
3367
|
-
var activeChildProcess, writeToActiveCommand, terminateActiveCommand, adjustWindowsCommand, exec_command;
|
|
3420
|
+
var pty, activeChildProcess, isActiveCommandPty, writeToActiveCommand, terminateActiveCommand, adjustWindowsCommand, exec_command, runStandardSpawn;
|
|
3368
3421
|
var init_exec_command = __esm({
|
|
3369
|
-
"src/tools/exec_command.js"() {
|
|
3422
|
+
async "src/tools/exec_command.js"() {
|
|
3370
3423
|
init_arg_parser();
|
|
3424
|
+
pty = null;
|
|
3425
|
+
try {
|
|
3426
|
+
const ptyModule = await import("node-pty");
|
|
3427
|
+
pty = ptyModule.default || ptyModule;
|
|
3428
|
+
} catch (err) {
|
|
3429
|
+
}
|
|
3371
3430
|
activeChildProcess = null;
|
|
3431
|
+
isActiveCommandPty = false;
|
|
3372
3432
|
writeToActiveCommand = (data) => {
|
|
3373
3433
|
try {
|
|
3374
|
-
if (activeChildProcess
|
|
3375
|
-
activeChildProcess.
|
|
3434
|
+
if (activeChildProcess) {
|
|
3435
|
+
if (isActiveCommandPty && typeof activeChildProcess.write === "function") {
|
|
3436
|
+
activeChildProcess.write(data);
|
|
3437
|
+
} else if (activeChildProcess.stdin && activeChildProcess.stdin.writable) {
|
|
3438
|
+
activeChildProcess.stdin.write(data);
|
|
3439
|
+
}
|
|
3376
3440
|
}
|
|
3377
3441
|
} catch (err) {
|
|
3378
3442
|
}
|
|
@@ -3380,13 +3444,18 @@ var init_exec_command = __esm({
|
|
|
3380
3444
|
terminateActiveCommand = () => {
|
|
3381
3445
|
if (activeChildProcess) {
|
|
3382
3446
|
try {
|
|
3383
|
-
activeChildProcess.
|
|
3447
|
+
if (isActiveCommandPty && typeof activeChildProcess.destroy === "function") {
|
|
3448
|
+
activeChildProcess.destroy();
|
|
3449
|
+
} else if (typeof activeChildProcess.kill === "function") {
|
|
3450
|
+
activeChildProcess.kill("SIGKILL");
|
|
3451
|
+
}
|
|
3384
3452
|
} catch (err) {
|
|
3385
3453
|
}
|
|
3386
3454
|
activeChildProcess = null;
|
|
3455
|
+
isActiveCommandPty = false;
|
|
3387
3456
|
}
|
|
3388
3457
|
};
|
|
3389
|
-
adjustWindowsCommand = (command) => {
|
|
3458
|
+
adjustWindowsCommand = (command, usePowerShell = false) => {
|
|
3390
3459
|
if (process.platform !== "win32") return command;
|
|
3391
3460
|
const tokens = [];
|
|
3392
3461
|
let current = "";
|
|
@@ -3423,7 +3492,7 @@ var init_exec_command = __esm({
|
|
|
3423
3492
|
tokens.push(current);
|
|
3424
3493
|
current = "";
|
|
3425
3494
|
}
|
|
3426
|
-
tokens.push("&");
|
|
3495
|
+
tokens.push(usePowerShell ? ";" : "&");
|
|
3427
3496
|
} else if (char === "|" && !current.includes("://")) {
|
|
3428
3497
|
if (current.length > 0) {
|
|
3429
3498
|
tokens.push(current);
|
|
@@ -3516,7 +3585,7 @@ var init_exec_command = __esm({
|
|
|
3516
3585
|
const { command: rawCommand } = parseArgs(args);
|
|
3517
3586
|
const { onChunk } = options;
|
|
3518
3587
|
if (!rawCommand) return 'ERROR: Missing "command" argument for exec_command.';
|
|
3519
|
-
const
|
|
3588
|
+
const isWin = process.platform === "win32";
|
|
3520
3589
|
const systemSettings = options.systemSettings || {};
|
|
3521
3590
|
const netEnv = {};
|
|
3522
3591
|
if (systemSettings.networkAccess === false) {
|
|
@@ -3529,58 +3598,127 @@ var init_exec_command = __esm({
|
|
|
3529
3598
|
netEnv.NO_PROXY = "localhost,127.0.0.1";
|
|
3530
3599
|
}
|
|
3531
3600
|
return new Promise((resolve) => {
|
|
3532
|
-
const
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3601
|
+
const attempt = (usePowerShell) => {
|
|
3602
|
+
const command = adjustWindowsCommand(rawCommand, usePowerShell);
|
|
3603
|
+
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
3604
|
+
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
3605
|
+
if (pty) {
|
|
3606
|
+
try {
|
|
3607
|
+
const ptyProcess = pty.spawn(shell, shellArgs, {
|
|
3608
|
+
name: "xterm-256color",
|
|
3609
|
+
cols: options.cols || 120,
|
|
3610
|
+
rows: options.rows || 30,
|
|
3611
|
+
cwd: process.cwd(),
|
|
3612
|
+
env: {
|
|
3613
|
+
...process.env,
|
|
3614
|
+
CI: "false",
|
|
3615
|
+
TERM: "xterm-256color",
|
|
3616
|
+
FORCE_COLOR: "1",
|
|
3617
|
+
...netEnv
|
|
3618
|
+
}
|
|
3619
|
+
});
|
|
3620
|
+
activeChildProcess = ptyProcess;
|
|
3621
|
+
isActiveCommandPty = true;
|
|
3622
|
+
let output = "";
|
|
3623
|
+
ptyProcess.onData((data) => {
|
|
3624
|
+
output += data;
|
|
3625
|
+
if (onChunk) onChunk(data);
|
|
3626
|
+
});
|
|
3627
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
3628
|
+
activeChildProcess = null;
|
|
3629
|
+
const finalOutput = output || "Command executed with no output.";
|
|
3630
|
+
if (exitCode !== 0) {
|
|
3631
|
+
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${exitCode}].
|
|
3632
|
+
|
|
3633
|
+
${finalOutput}`);
|
|
3634
|
+
} else {
|
|
3635
|
+
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
3636
|
+
|
|
3637
|
+
${finalOutput}`);
|
|
3638
|
+
}
|
|
3639
|
+
});
|
|
3640
|
+
return true;
|
|
3641
|
+
} catch (err) {
|
|
3642
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
3643
|
+
return false;
|
|
3644
|
+
}
|
|
3645
|
+
runStandardSpawn(resolve, command, rawCommand, netEnv, onChunk, usePowerShell);
|
|
3646
|
+
return true;
|
|
3647
|
+
}
|
|
3648
|
+
} else {
|
|
3649
|
+
runStandardSpawn(resolve, command, rawCommand, netEnv, onChunk, usePowerShell);
|
|
3650
|
+
return true;
|
|
3541
3651
|
}
|
|
3542
|
-
}
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3652
|
+
};
|
|
3653
|
+
if (isWin) {
|
|
3654
|
+
if (!attempt(true)) {
|
|
3655
|
+
attempt(false);
|
|
3656
|
+
}
|
|
3657
|
+
} else {
|
|
3658
|
+
attempt(false);
|
|
3548
3659
|
}
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3660
|
+
});
|
|
3661
|
+
};
|
|
3662
|
+
runStandardSpawn = (resolve, command, rawCommand, netEnv, onChunk, usePowerShell = true) => {
|
|
3663
|
+
const isWin = process.platform === "win32";
|
|
3664
|
+
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
3665
|
+
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
3666
|
+
const child = isWin ? spawn(shell, shellArgs, { cwd: process.cwd(), env: { ...process.env, ...netEnv } }) : spawn(command, {
|
|
3667
|
+
shell: true,
|
|
3668
|
+
cwd: process.cwd(),
|
|
3669
|
+
env: {
|
|
3670
|
+
...process.env,
|
|
3671
|
+
CI: "false",
|
|
3672
|
+
TERM: "xterm-256color",
|
|
3673
|
+
FORCE_COLOR: "1",
|
|
3674
|
+
...netEnv
|
|
3675
|
+
}
|
|
3676
|
+
});
|
|
3677
|
+
activeChildProcess = child;
|
|
3678
|
+
isActiveCommandPty = false;
|
|
3679
|
+
if (child.stdin) {
|
|
3680
|
+
child.stdin.on("error", () => {
|
|
3562
3681
|
activeChildProcess = null;
|
|
3563
|
-
|
|
3564
|
-
|
|
3682
|
+
});
|
|
3683
|
+
}
|
|
3684
|
+
let stdout = "";
|
|
3685
|
+
let stderr = "";
|
|
3686
|
+
child.stdout.on("data", (data) => {
|
|
3687
|
+
const chunk = data.toString();
|
|
3688
|
+
stdout += chunk;
|
|
3689
|
+
if (onChunk) onChunk(chunk);
|
|
3690
|
+
});
|
|
3691
|
+
child.stderr.on("data", (data) => {
|
|
3692
|
+
const chunk = data.toString();
|
|
3693
|
+
stderr += chunk;
|
|
3694
|
+
if (onChunk) onChunk(chunk);
|
|
3695
|
+
});
|
|
3696
|
+
child.on("close", (code) => {
|
|
3697
|
+
activeChildProcess = null;
|
|
3698
|
+
const result = [];
|
|
3699
|
+
if (stdout) result.push(`STDOUT:
|
|
3565
3700
|
${stdout}`);
|
|
3566
|
-
|
|
3701
|
+
if (stderr) result.push(`STDERR:
|
|
3567
3702
|
${stderr}`);
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3703
|
+
if (code !== 0) result.push(`EXIT CODE: ${code}`);
|
|
3704
|
+
const finalOutput = result.join("\n\n") || "Command executed with no output.";
|
|
3705
|
+
if (code !== 0) {
|
|
3706
|
+
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${code}].
|
|
3572
3707
|
|
|
3573
3708
|
${finalOutput}`);
|
|
3574
|
-
|
|
3575
|
-
|
|
3709
|
+
} else {
|
|
3710
|
+
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
3576
3711
|
|
|
3577
3712
|
${finalOutput}`);
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3713
|
+
}
|
|
3714
|
+
});
|
|
3715
|
+
child.on("error", (err) => {
|
|
3716
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
3717
|
+
const cmdCommand = adjustWindowsCommand(rawCommand, false);
|
|
3718
|
+
return runStandardSpawn(resolve, cmdCommand, rawCommand, netEnv, onChunk, false);
|
|
3719
|
+
}
|
|
3720
|
+
activeChildProcess = null;
|
|
3721
|
+
resolve(`ERROR: Failed to start command [${rawCommand}]: ${err.message}`);
|
|
3584
3722
|
});
|
|
3585
3723
|
};
|
|
3586
3724
|
}
|
|
@@ -3916,33 +4054,44 @@ var init_search_keyword = __esm({
|
|
|
3916
4054
|
"src/tools/search_keyword.js"() {
|
|
3917
4055
|
init_arg_parser();
|
|
3918
4056
|
search_keyword = async (args) => {
|
|
3919
|
-
const { keyword } = parseArgs(args);
|
|
4057
|
+
const { keyword, file } = parseArgs(args);
|
|
3920
4058
|
if (!keyword) return 'ERROR: Missing "keyword" argument.';
|
|
3921
4059
|
const isWindows = process.platform === "win32";
|
|
3922
4060
|
const excludes = ["node_modules", ".git", "dist", ".next", ".gemini"];
|
|
3923
4061
|
let command = "";
|
|
3924
|
-
if (
|
|
3925
|
-
|
|
3926
|
-
|
|
4062
|
+
if (file) {
|
|
4063
|
+
if (isWindows) {
|
|
4064
|
+
command = `powershell -Command "if (Test-Path '${file}') { Select-String -Path '${file}' -Pattern '${keyword}' | Select-Object -First 150 | ForEach-Object { $rel = Resolve-Path $_.Path -Relative; '{0}:{1}:' -f $rel, $_.LineNumber } } else { Write-Error 'File not found: ${file}' }"`;
|
|
4065
|
+
} else {
|
|
4066
|
+
command = `grep -HnI "${keyword}" "${file}" | head -n 150`;
|
|
4067
|
+
}
|
|
3927
4068
|
} else {
|
|
3928
|
-
|
|
3929
|
-
|
|
4069
|
+
if (isWindows) {
|
|
4070
|
+
const excludePattern = excludes.join("|").replace(/\./g, "\\.");
|
|
4071
|
+
command = `powershell -Command "Get-ChildItem -Path . -Recurse -File | Where-Object { $_.FullName -notmatch '${excludePattern}' } | Select-String -Pattern '${keyword}' | Select-Object -First 150 | ForEach-Object { $rel = Resolve-Path $_.Path -Relative; '{0}:{1}:' -f $rel, $_.LineNumber }"`;
|
|
4072
|
+
} else {
|
|
4073
|
+
const excludeDirArgs = excludes.map((d) => `--exclude-dir="${d}"`).join(" ");
|
|
4074
|
+
command = `grep -rnI ${excludeDirArgs} "${keyword}" . | head -n 150`;
|
|
4075
|
+
}
|
|
3930
4076
|
}
|
|
3931
4077
|
return new Promise((resolve) => {
|
|
3932
4078
|
exec(command, { cwd: process.cwd(), maxBuffer: 15 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
4079
|
+
if (error && stderr && stderr.includes("File not found")) {
|
|
4080
|
+
return resolve(`ERROR: File not found: ${file}`);
|
|
4081
|
+
}
|
|
3933
4082
|
if (error && error.code === 1 && !stdout) {
|
|
3934
|
-
return resolve(`Found 0 matches for keyword: "${keyword}"`);
|
|
4083
|
+
return resolve(`Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ""}`);
|
|
3935
4084
|
}
|
|
3936
4085
|
if (error && !stdout) {
|
|
3937
4086
|
return resolve(`ERROR: ${stderr || error.message}`);
|
|
3938
4087
|
}
|
|
3939
4088
|
const rawLines = stdout.trim().split("\n").filter((l) => l.trim() !== "");
|
|
3940
|
-
if (rawLines.length === 0) return resolve(`Found 0 matches for keyword: "${keyword}"`);
|
|
4089
|
+
if (rawLines.length === 0) return resolve(`Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ""}`);
|
|
3941
4090
|
const filteredLines = rawLines.filter((line) => {
|
|
3942
4091
|
const lower = line.toLowerCase();
|
|
3943
4092
|
return !lower.includes("node_modules") && !lower.includes(".git") && !lower.includes("dist") && !lower.includes(".next") && !lower.includes(".gemini");
|
|
3944
4093
|
});
|
|
3945
|
-
if (filteredLines.length === 0) return resolve(`Found 0 matches for keyword: "${keyword}"`);
|
|
4094
|
+
if (filteredLines.length === 0) return resolve(`Found 0 matches for keyword: "${keyword}"${file ? ` in file: ${file}` : ""}`);
|
|
3946
4095
|
const matches = filteredLines.slice(0, 150).map((line) => {
|
|
3947
4096
|
const firstColon = line.indexOf(":");
|
|
3948
4097
|
const secondColon = line.indexOf(":", firstColon + 1);
|
|
@@ -4385,7 +4534,7 @@ var init_addMemScore = __esm({
|
|
|
4385
4534
|
// src/utils/tools.js
|
|
4386
4535
|
var TOOL_MAP, dispatchTool;
|
|
4387
4536
|
var init_tools = __esm({
|
|
4388
|
-
"src/utils/tools.js"() {
|
|
4537
|
+
async "src/utils/tools.js"() {
|
|
4389
4538
|
init_web_search();
|
|
4390
4539
|
init_web_scrape();
|
|
4391
4540
|
init_memory();
|
|
@@ -4393,7 +4542,7 @@ var init_tools = __esm({
|
|
|
4393
4542
|
init_view_file();
|
|
4394
4543
|
init_write_file();
|
|
4395
4544
|
init_update_file();
|
|
4396
|
-
init_exec_command();
|
|
4545
|
+
await init_exec_command();
|
|
4397
4546
|
init_read_folder();
|
|
4398
4547
|
init_ask_user();
|
|
4399
4548
|
init_write_pdf();
|
|
@@ -4462,11 +4611,11 @@ import path15 from "path";
|
|
|
4462
4611
|
import fs16 from "fs";
|
|
4463
4612
|
var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, consolidatePastMemories, getAIStream;
|
|
4464
4613
|
var init_ai = __esm({
|
|
4465
|
-
"src/utils/ai.js"() {
|
|
4614
|
+
async "src/utils/ai.js"() {
|
|
4466
4615
|
init_prompts();
|
|
4467
4616
|
init_history();
|
|
4468
4617
|
init_usage();
|
|
4469
|
-
init_tools();
|
|
4618
|
+
await init_tools();
|
|
4470
4619
|
init_crypto();
|
|
4471
4620
|
init_arg_parser();
|
|
4472
4621
|
init_terminal();
|
|
@@ -5015,7 +5164,7 @@ ${newMemoryListStr}
|
|
|
5015
5164
|
const isContext32k = (sessionStats?.tokens || 0) >= 32e3;
|
|
5016
5165
|
const memoryPrompt = getMemoryPrompt(otherMemories, mainUserMemories, isMemoryEnabled, isContext32k);
|
|
5017
5166
|
const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: true });
|
|
5018
|
-
const getDirTree = (dir, prefix = "") => {
|
|
5167
|
+
const getDirTree = (dir, prefix = "", depth = 1) => {
|
|
5019
5168
|
try {
|
|
5020
5169
|
const files = fs16.readdirSync(dir);
|
|
5021
5170
|
const sep = path15.sep;
|
|
@@ -5052,13 +5201,13 @@ ${newMemoryListStr}
|
|
|
5052
5201
|
const stat = fs16.statSync(filePath);
|
|
5053
5202
|
if (stat.isDirectory()) {
|
|
5054
5203
|
const subFiles = fs16.readdirSync(filePath);
|
|
5055
|
-
if (subFiles.length > 80) {
|
|
5204
|
+
if (subFiles.length > 80 || depth >= 7) {
|
|
5056
5205
|
result += `${prefix}${connector}${file}${sep}...
|
|
5057
5206
|
`;
|
|
5058
5207
|
} else {
|
|
5059
5208
|
result += `${prefix}${connector}${file}${sep}
|
|
5060
5209
|
`;
|
|
5061
|
-
result += getDirTree(filePath, childPrefix);
|
|
5210
|
+
result += getDirTree(filePath, childPrefix, depth + 1);
|
|
5062
5211
|
}
|
|
5063
5212
|
} else {
|
|
5064
5213
|
result += `${prefix}${connector}${file}
|
|
@@ -5076,7 +5225,7 @@ ${newMemoryListStr}
|
|
|
5076
5225
|
};
|
|
5077
5226
|
yield { type: "status", content: "Gathering Context..." };
|
|
5078
5227
|
let dirStructure = process.cwd() + "\n" + getDirTree(process.cwd());
|
|
5079
|
-
const firstUserMsg = `[METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
|
|
5228
|
+
const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
|
|
5080
5229
|
CWD: ${process.cwd()}
|
|
5081
5230
|
**DIRECTORY STRUCTURE**
|
|
5082
5231
|
${dirStructure}
|
|
@@ -5178,8 +5327,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITI
|
|
|
5178
5327
|
}
|
|
5179
5328
|
const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
|
|
5180
5329
|
const jitInstruction = `
|
|
5181
|
-
|
|
5182
|
-
[SYSTEM] Tool result received. Analyze output and proceed with your turn.${thinkingLevel != "Fast" ? "**STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**" : ""}`;
|
|
5330
|
+
[SYSTEM] Tool result received. Analyze output and proceed with your turn${thinkingLevel != "Fast" ? ". **STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**" : ""}`;
|
|
5183
5331
|
const lastUserMsg = contents[contents.length - 1];
|
|
5184
5332
|
let addedMarker = false;
|
|
5185
5333
|
if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
|
|
@@ -5800,7 +5948,7 @@ ${boxBottom}` };
|
|
|
5800
5948
|
const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
|
|
5801
5949
|
if (turnText.trim().length > 0) {
|
|
5802
5950
|
modifiedHistory.push({ role: "agent", text: turnText });
|
|
5803
|
-
const recoveryText = "[SYSTEM
|
|
5951
|
+
const recoveryText = "[SYSTEM]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption\n- NO REPETITION: Do not repeat any text already written\n- NO RE-THINK: Do not restart or open <think> if reasoning already started. Continue the thinking and close thinking block with </think> if opened\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start\n- STEALTH: Do not mention/apologize for cutoff";
|
|
5804
5952
|
if (toolResults.length > 0) {
|
|
5805
5953
|
toolResults.forEach((tr, idx) => {
|
|
5806
5954
|
if (idx === toolResults.length - 1) {
|
|
@@ -5820,7 +5968,7 @@ ${recoveryText}`
|
|
|
5820
5968
|
accumulatedContext += turnText;
|
|
5821
5969
|
}
|
|
5822
5970
|
for (let i = waitTime / 1e3; i > 0; i--) {
|
|
5823
|
-
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
|
|
5971
|
+
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [Retrying in ${i}s]...` };
|
|
5824
5972
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
5825
5973
|
}
|
|
5826
5974
|
yield { type: "status", content: `Error Occured. Recovering Stream...` };
|
|
@@ -5835,14 +5983,14 @@ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
5835
5983
|
accumulatedContext = "";
|
|
5836
5984
|
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 32e3);
|
|
5837
5985
|
isInitialAttempt = true;
|
|
5838
|
-
yield { type: "status", content: `
|
|
5986
|
+
yield { type: "status", content: `Trying to reach ${modelName} (${retryCount}/${MAX_RETRIES}) [Retrying in ${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
5839
5987
|
for (let i = waitTime / 1e3; i > 0; i--) {
|
|
5840
|
-
yield { type: "status", content: `
|
|
5988
|
+
yield { type: "status", content: `Trying to reach ${modelName} (${retryCount}/${MAX_RETRIES}) [Retrying in ${i}s]...` };
|
|
5841
5989
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
5842
5990
|
}
|
|
5843
|
-
yield { type: "status", content: `
|
|
5991
|
+
yield { type: "status", content: `Trying to reach ${modelName}...` };
|
|
5844
5992
|
} else {
|
|
5845
|
-
throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
5993
|
+
throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
5846
5994
|
Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
|
|
5847
5995
|
}
|
|
5848
5996
|
}
|
|
@@ -6092,15 +6240,28 @@ var init_MemoryModal = __esm({
|
|
|
6092
6240
|
// src/components/UpdateProcessor.jsx
|
|
6093
6241
|
import React11, { useState as useState8, useEffect as useEffect6 } from "react";
|
|
6094
6242
|
import { Box as Box11, Text as Text11 } from "ink";
|
|
6095
|
-
import
|
|
6096
|
-
|
|
6097
|
-
var UpdateProcessor, UpdateProcessor_default;
|
|
6243
|
+
import { spawn as spawn2 } from "child_process";
|
|
6244
|
+
var pty2, SPINNER_FRAMES, UpdateProcessor, UpdateProcessor_default;
|
|
6098
6245
|
var init_UpdateProcessor = __esm({
|
|
6099
|
-
"src/components/UpdateProcessor.jsx"() {
|
|
6246
|
+
async "src/components/UpdateProcessor.jsx"() {
|
|
6247
|
+
pty2 = null;
|
|
6248
|
+
try {
|
|
6249
|
+
const ptyModule = await import("node-pty");
|
|
6250
|
+
pty2 = ptyModule.default || ptyModule;
|
|
6251
|
+
} catch (err) {
|
|
6252
|
+
}
|
|
6253
|
+
SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
6100
6254
|
UpdateProcessor = ({ latest, current, settings, onClose, onUpdateSettings, onSuccess }) => {
|
|
6101
6255
|
const [status, setStatus] = useState8("initializing");
|
|
6102
6256
|
const [log, setLog] = useState8("");
|
|
6103
6257
|
const [error, setError] = useState8(null);
|
|
6258
|
+
const [tick, setTick] = useState8(0);
|
|
6259
|
+
useEffect6(() => {
|
|
6260
|
+
const interval = setInterval(() => {
|
|
6261
|
+
setTick((t) => (t + 1) % 1e3);
|
|
6262
|
+
}, 33);
|
|
6263
|
+
return () => clearInterval(interval);
|
|
6264
|
+
}, []);
|
|
6104
6265
|
useEffect6(() => {
|
|
6105
6266
|
let child;
|
|
6106
6267
|
const runUpdate = async () => {
|
|
@@ -6117,31 +6278,101 @@ var init_UpdateProcessor = __esm({
|
|
|
6117
6278
|
else command = `npm install -g fluxflow-cli@${latest}`;
|
|
6118
6279
|
setStatus("downloading");
|
|
6119
6280
|
setLog(`Running: ${command}...`);
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6281
|
+
const isWin = process.platform === "win32";
|
|
6282
|
+
const executeCommand = (usePowerShell) => {
|
|
6283
|
+
return new Promise((resolve) => {
|
|
6284
|
+
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
6285
|
+
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
6286
|
+
const handleOutput = (data) => {
|
|
6287
|
+
const str = data.toString();
|
|
6288
|
+
const cleanStr = str.replace(/\x1B\[[0-?]*[ -/]*[@-~]|\x1B\][^\x07\x1B]*[\x07\x1B]|\b|\x07/g, "").replace(/\r/g, "").trim();
|
|
6289
|
+
if (cleanStr) {
|
|
6290
|
+
setLog((prev) => (prev + "\n" + cleanStr).split("\n").slice(-5).join("\n"));
|
|
6291
|
+
}
|
|
6292
|
+
};
|
|
6293
|
+
if (pty2) {
|
|
6294
|
+
try {
|
|
6295
|
+
const ptyProcess = pty2.spawn(shell, shellArgs, {
|
|
6296
|
+
name: "xterm-256color",
|
|
6297
|
+
cols: 80,
|
|
6298
|
+
rows: 30,
|
|
6299
|
+
cwd: process.cwd(),
|
|
6300
|
+
env: process.env
|
|
6301
|
+
});
|
|
6302
|
+
child = ptyProcess;
|
|
6303
|
+
ptyProcess.onData(handleOutput);
|
|
6304
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
6305
|
+
child = null;
|
|
6306
|
+
if (exitCode !== 0) {
|
|
6307
|
+
resolve({ error: `Process exited with code ${exitCode}` });
|
|
6308
|
+
} else {
|
|
6309
|
+
resolve({ success: true });
|
|
6310
|
+
}
|
|
6311
|
+
});
|
|
6312
|
+
return;
|
|
6313
|
+
} catch (err) {
|
|
6314
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
6315
|
+
resolve({ retryCmd: true });
|
|
6316
|
+
return;
|
|
6317
|
+
}
|
|
6318
|
+
}
|
|
6319
|
+
}
|
|
6320
|
+
const cp = isWin ? spawn2(shell, shellArgs, { cwd: process.cwd(), env: process.env }) : spawn2(command, { shell: true, cwd: process.cwd(), env: process.env });
|
|
6321
|
+
child = cp;
|
|
6322
|
+
cp.stdout.on("data", handleOutput);
|
|
6323
|
+
cp.stderr.on("data", handleOutput);
|
|
6324
|
+
cp.on("close", (code) => {
|
|
6325
|
+
child = null;
|
|
6326
|
+
if (code !== 0) {
|
|
6327
|
+
resolve({ error: `Process exited with code ${code}` });
|
|
6328
|
+
} else {
|
|
6329
|
+
resolve({ success: true });
|
|
6330
|
+
}
|
|
6331
|
+
});
|
|
6332
|
+
cp.on("error", (err) => {
|
|
6333
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
6334
|
+
resolve({ retryCmd: true });
|
|
6335
|
+
} else {
|
|
6336
|
+
child = null;
|
|
6337
|
+
resolve({ error: err.message });
|
|
6338
|
+
}
|
|
6339
|
+
});
|
|
6340
|
+
});
|
|
6341
|
+
};
|
|
6342
|
+
let result = {};
|
|
6343
|
+
if (isWin) {
|
|
6344
|
+
result = await executeCommand(true);
|
|
6345
|
+
if (result.retryCmd) {
|
|
6346
|
+
result = await executeCommand(false);
|
|
6125
6347
|
}
|
|
6348
|
+
} else {
|
|
6349
|
+
result = await executeCommand(false);
|
|
6350
|
+
}
|
|
6351
|
+
if (result.error) {
|
|
6352
|
+
setError(result.error);
|
|
6353
|
+
setStatus("error");
|
|
6354
|
+
} else if (result.success) {
|
|
6126
6355
|
setStatus("success");
|
|
6127
6356
|
if (onSuccess) onSuccess();
|
|
6128
|
-
}
|
|
6129
|
-
child.stdout.on("data", (data) => {
|
|
6130
|
-
setLog((prev) => (prev + "\n" + data).split("\n").slice(-5).join("\n"));
|
|
6131
|
-
});
|
|
6357
|
+
}
|
|
6132
6358
|
};
|
|
6133
6359
|
runUpdate();
|
|
6134
6360
|
return () => {
|
|
6135
6361
|
if (child) {
|
|
6136
6362
|
try {
|
|
6137
|
-
child.
|
|
6363
|
+
if (typeof child.destroy === "function") {
|
|
6364
|
+
child.destroy();
|
|
6365
|
+
} else if (typeof child.kill === "function") {
|
|
6366
|
+
child.kill();
|
|
6367
|
+
}
|
|
6138
6368
|
} catch (e) {
|
|
6139
6369
|
}
|
|
6140
6370
|
}
|
|
6141
6371
|
};
|
|
6142
6372
|
}, []);
|
|
6143
6373
|
if (status === "initializing" || status === "downloading") {
|
|
6144
|
-
|
|
6374
|
+
const frame = SPINNER_FRAMES[Math.floor(tick / 3) % SPINNER_FRAMES.length];
|
|
6375
|
+
return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text11, { color: "magenta" }, frame), /* @__PURE__ */ React11.createElement(Text11, { marginLeft: 1, bold: true }, " Updating Flux Flow to v", latest, "...")), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1, paddingX: 1, borderStyle: "single", borderColor: "#333" }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, log || "Preparing environment...")), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, dimColor: true }, "(Please do not close the terminal)"));
|
|
6145
6376
|
}
|
|
6146
6377
|
if (status === "success") {
|
|
6147
6378
|
return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "green", bold: true }, "\u2705 UPDATE SUCCESSFUL!"), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "Flux Flow has been updated to ", /* @__PURE__ */ React11.createElement(Text11, { color: "cyan" }, "v", latest), "."), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, color: "yellow", bold: true }, "CRITICAL: Please restart your terminal session to apply changes."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { dimColor: true }, "(Press ESC to return to chat)")));
|
|
@@ -6241,13 +6472,13 @@ var init_RevertModal = __esm({
|
|
|
6241
6472
|
|
|
6242
6473
|
// src/utils/setup.js
|
|
6243
6474
|
import puppeteer4 from "puppeteer";
|
|
6244
|
-
import { exec as
|
|
6475
|
+
import { exec as exec2 } from "child_process";
|
|
6245
6476
|
import { promisify } from "util";
|
|
6246
6477
|
import fs17 from "fs";
|
|
6247
6478
|
var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
|
|
6248
6479
|
var init_setup = __esm({
|
|
6249
6480
|
"src/utils/setup.js"() {
|
|
6250
|
-
execAsync = promisify(
|
|
6481
|
+
execAsync = promisify(exec2);
|
|
6251
6482
|
checkPuppeteerReady = () => {
|
|
6252
6483
|
try {
|
|
6253
6484
|
const exePath = puppeteer4.executablePath();
|
|
@@ -6284,10 +6515,9 @@ __export(app_exports, {
|
|
|
6284
6515
|
import os4 from "os";
|
|
6285
6516
|
import React13, { useState as useState10, useEffect as useEffect7, useRef as useRef3, useMemo as useMemo2 } from "react";
|
|
6286
6517
|
import { Box as Box13, Text as Text13, useInput as useInput7, useStdout } from "ink";
|
|
6287
|
-
import Spinner2 from "ink-spinner";
|
|
6288
6518
|
import fs18 from "fs-extra";
|
|
6289
6519
|
import path16 from "path";
|
|
6290
|
-
import { exec as
|
|
6520
|
+
import { exec as exec3 } from "child_process";
|
|
6291
6521
|
import { fileURLToPath } from "url";
|
|
6292
6522
|
import TextInput4 from "ink-text-input";
|
|
6293
6523
|
import gradient from "gradient-string";
|
|
@@ -6439,6 +6669,7 @@ function App({ args = [] }) {
|
|
|
6439
6669
|
const [activeCommand, setActiveCommand] = useState10(null);
|
|
6440
6670
|
const [execOutput, setExecOutput] = useState10("");
|
|
6441
6671
|
const [isTerminalFocused, setIsTerminalFocused] = useState10(false);
|
|
6672
|
+
const [tick, setTick] = useState10(0);
|
|
6442
6673
|
useEffect7(() => {
|
|
6443
6674
|
if (apiTier !== "Free" && activeModel === "gemma-4-31b-it") {
|
|
6444
6675
|
setActiveModel("gemini-3-flash-preview");
|
|
@@ -6579,13 +6810,17 @@ function App({ args = [] }) {
|
|
|
6579
6810
|
if (key.return) {
|
|
6580
6811
|
const isWin = process.platform === "win32";
|
|
6581
6812
|
writeToActiveCommand(isWin ? "\r\n" : "\n");
|
|
6582
|
-
setExecOutput((prev) => prev + "\n");
|
|
6813
|
+
if (!isActiveCommandPty) setExecOutput((prev) => prev + "\n");
|
|
6583
6814
|
} else if (key.backspace || key.delete) {
|
|
6584
|
-
|
|
6585
|
-
|
|
6815
|
+
if (isActiveCommandPty) {
|
|
6816
|
+
writeToActiveCommand("\x7F");
|
|
6817
|
+
} else {
|
|
6818
|
+
writeToActiveCommand("\b \b");
|
|
6819
|
+
setExecOutput((prev) => prev.slice(0, -1));
|
|
6820
|
+
}
|
|
6586
6821
|
} else if (inputText) {
|
|
6587
6822
|
writeToActiveCommand(inputText);
|
|
6588
|
-
setExecOutput((prev) => prev + inputText);
|
|
6823
|
+
if (!isActiveCommandPty) setExecOutput((prev) => prev + inputText);
|
|
6589
6824
|
}
|
|
6590
6825
|
return;
|
|
6591
6826
|
}
|
|
@@ -6634,17 +6869,21 @@ function App({ args = [] }) {
|
|
|
6634
6869
|
} else if (nextCount === 2) {
|
|
6635
6870
|
if (escDoubleTimerRef.current) clearTimeout(escDoubleTimerRef.current);
|
|
6636
6871
|
setEscPressCount(0);
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6872
|
+
if (input.length > 0) {
|
|
6873
|
+
setInput("");
|
|
6874
|
+
} else {
|
|
6875
|
+
RevertManager.getChatHistory(chatId).then((prompts) => {
|
|
6876
|
+
if (prompts.length > 0) {
|
|
6877
|
+
setRecentPrompts(prompts.reverse());
|
|
6878
|
+
setActiveView("revert");
|
|
6879
|
+
} else {
|
|
6880
|
+
setMessages((prev2) => {
|
|
6881
|
+
setCompletedIndex(prev2.length + 1);
|
|
6882
|
+
return [...prev2, { id: "revert-empty-" + Date.now(), role: "system", text: "\u{1F6C8} No revert checkpoints found for this session.", isMeta: true }];
|
|
6883
|
+
});
|
|
6884
|
+
}
|
|
6885
|
+
});
|
|
6886
|
+
}
|
|
6648
6887
|
}
|
|
6649
6888
|
return nextCount;
|
|
6650
6889
|
});
|
|
@@ -6667,6 +6906,10 @@ function App({ args = [] }) {
|
|
|
6667
6906
|
if (key.tab && activeView === "chat") {
|
|
6668
6907
|
}
|
|
6669
6908
|
if (key.ctrl && inputText === "c" && activeView !== "exit") {
|
|
6909
|
+
if (input.length > 0) {
|
|
6910
|
+
setInput("");
|
|
6911
|
+
return;
|
|
6912
|
+
}
|
|
6670
6913
|
if (key.shift) {
|
|
6671
6914
|
setActiveView("exit");
|
|
6672
6915
|
setConfirmExit(false);
|
|
@@ -7100,7 +7343,7 @@ ${hintText}`, color: "magenta" }];
|
|
|
7100
7343
|
isMeta: true
|
|
7101
7344
|
}];
|
|
7102
7345
|
});
|
|
7103
|
-
|
|
7346
|
+
exec3("start https://enter.pollinations.ai/#pollen");
|
|
7104
7347
|
} else {
|
|
7105
7348
|
try {
|
|
7106
7349
|
const stats = await getImageQuotaStats();
|
|
@@ -7426,7 +7669,7 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
7426
7669
|
case "/changelog": {
|
|
7427
7670
|
const platform = process.platform;
|
|
7428
7671
|
const command = platform === "win32" ? "start" : platform === "darwin" ? "open" : "xdg-open";
|
|
7429
|
-
|
|
7672
|
+
exec3(`${command} ${CHANGELOG_URL}`);
|
|
7430
7673
|
setMessages((prev) => {
|
|
7431
7674
|
setCompletedIndex(prev.length + 1);
|
|
7432
7675
|
return [...prev, { id: Date.now(), role: "system", text: `\u{1F310} [BROWSER] Opening changelog: ${CHANGELOG_URL}`, isMeta: true }];
|
|
@@ -7530,6 +7773,8 @@ ${timestamp}` };
|
|
|
7530
7773
|
janitorModel,
|
|
7531
7774
|
sessionStats,
|
|
7532
7775
|
chatId,
|
|
7776
|
+
cols: terminalSize.columns - 6,
|
|
7777
|
+
rows: 30,
|
|
7533
7778
|
onExecStart: (cmd) => {
|
|
7534
7779
|
setActiveCommand(cmd);
|
|
7535
7780
|
setExecOutput("");
|
|
@@ -7542,6 +7787,7 @@ ${timestamp}` };
|
|
|
7542
7787
|
if (!activeCommandRef.current) return prev;
|
|
7543
7788
|
const finalStatus = `[TERMINAL_RECORD]
|
|
7544
7789
|
COMMAND: ${activeCommandRef.current}
|
|
7790
|
+
PTY: ${isActiveCommandPty}
|
|
7545
7791
|
OUTPUT: ${execOutputRef.current}`;
|
|
7546
7792
|
return [...prev, { id: "term-" + Date.now(), role: "system", text: finalStatus, isTerminalRecord: true }];
|
|
7547
7793
|
});
|
|
@@ -8431,7 +8677,7 @@ Selection: ${val}`,
|
|
|
8431
8677
|
}
|
|
8432
8678
|
)));
|
|
8433
8679
|
default:
|
|
8434
|
-
return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, null, statusText ? /* @__PURE__ */ React13.createElement(Box13, null, isSpinnerActive && /* @__PURE__ */ React13.createElement(
|
|
8680
|
+
return /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, null, statusText ? /* @__PURE__ */ React13.createElement(Box13, null, isSpinnerActive && /* @__PURE__ */ React13.createElement(StatusSpinner, null), /* @__PURE__ */ React13.createElement(Text13, { color: "magenta", bold: true, italic: true }, isSpinnerActive ? " " : "", statusText.toUpperCase())) : /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", dimColor: true, italic: true }, "READY FOR COMMAND...")), /* @__PURE__ */ React13.createElement(Box13, null, /* @__PURE__ */ React13.createElement(Text13, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React13.createElement(Text13, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React13.createElement(Text13, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React13.createElement(
|
|
8435
8681
|
Box13,
|
|
8436
8682
|
{
|
|
8437
8683
|
borderStyle: "round",
|
|
@@ -8457,12 +8703,13 @@ Selection: ${val}`,
|
|
|
8457
8703
|
newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
|
|
8458
8704
|
}
|
|
8459
8705
|
}
|
|
8460
|
-
)))) : /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React13.createElement(Box13, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React13.createElement(Text13, { color: isProcessing ? "magenta" : "cyan", bold: true }, isProcessing ? "\u2726 " : "\u{1F4A0} ")), /* @__PURE__ */ React13.createElement(Box13, { flexGrow: 1 }, /* @__PURE__ */ React13.createElement(Box13, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React13.createElement(Box13, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React13.createElement(Text13, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React13.createElement(Text13, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : escPressCount === 1 ? /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", bold: true }, " Press ESC again to revert codebase to checkpoint...") : /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Send message or /cmd... (${terminalEnv.shortcut} for newline)` : " Enter a prompt to steer the agent.")), /* @__PURE__ */ React13.createElement(
|
|
8706
|
+
)))) : /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React13.createElement(Box13, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React13.createElement(Text13, { color: isProcessing ? "magenta" : "cyan", bold: true }, isProcessing ? "\u2726 " : "\u{1F4A0} ")), /* @__PURE__ */ React13.createElement(Box13, { flexGrow: 1 }, /* @__PURE__ */ React13.createElement(Box13, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React13.createElement(Box13, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React13.createElement(Text13, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React13.createElement(Text13, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : escPressCount === 1 ? /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", bold: true }, " Press ESC again to ", input.length > 0 ? "clear input" : "revert codebase to checkpoint", "...") : /* @__PURE__ */ React13.createElement(Text13, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Send message or /cmd... (${terminalEnv.shortcut} for newline)` : " Enter a prompt to steer the agent.")), /* @__PURE__ */ React13.createElement(
|
|
8461
8707
|
MultilineInput,
|
|
8462
8708
|
{
|
|
8463
8709
|
key: `input-${inputKey}`,
|
|
8464
8710
|
focus: !isTerminalFocused,
|
|
8465
8711
|
value: input,
|
|
8712
|
+
columns: terminalSize.columns,
|
|
8466
8713
|
onChange: (val) => {
|
|
8467
8714
|
const cleanVal = val.replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\\\s*\n/g, "\n");
|
|
8468
8715
|
setInput(cleanVal);
|
|
@@ -8486,7 +8733,7 @@ Selection: ${val}`,
|
|
|
8486
8733
|
showFullThinking,
|
|
8487
8734
|
columns: Math.max(20, (stdout?.columns || 80) - 1)
|
|
8488
8735
|
}
|
|
8489
|
-
), activeCommand && /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused }))), isInitializing ? /* @__PURE__ */ React13.createElement(Box13, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React13.createElement(Text13, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React13.createElement(Box13, { borderStyle: "round", borderColor: "gray", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "yellow", bold: true }, "\u{1F511}", emojiSpace(2), "API KEY REQUIRED")), /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text13, null, "Please enter your Gemini API Key to initialize the agent."), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React13.createElement(
|
|
8736
|
+
), activeCommand && /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused, isPty: isActiveCommandPty }))), isInitializing ? /* @__PURE__ */ React13.createElement(Box13, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React13.createElement(Text13, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React13.createElement(Box13, { borderStyle: "round", borderColor: "gray", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "yellow", bold: true }, "\u{1F511}", emojiSpace(2), "API KEY REQUIRED")), /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React13.createElement(Text13, null, "Please enter your Gemini API Key to initialize the agent."), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React13.createElement(
|
|
8490
8737
|
TextInput4,
|
|
8491
8738
|
{
|
|
8492
8739
|
value: tempKey,
|
|
@@ -8561,9 +8808,9 @@ Selection: ${val}`,
|
|
|
8561
8808
|
);
|
|
8562
8809
|
})()));
|
|
8563
8810
|
}
|
|
8564
|
-
var SESSION_START_TIME, CHANGELOG_URL, linesAdded, linesRemoved, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, FLUX_LOGO, parseAgentText, getProjectFiles;
|
|
8811
|
+
var SESSION_START_TIME, CHANGELOG_URL, linesAdded, linesRemoved, packageJsonPath, packageJson, versionFluxflow, updatedOn, SPINNER_FRAMES2, StatusSpinner, ResolutionModal, FLUX_LOGO, parseAgentText, getProjectFiles;
|
|
8565
8812
|
var init_app = __esm({
|
|
8566
|
-
"src/app.jsx"() {
|
|
8813
|
+
async "src/app.jsx"() {
|
|
8567
8814
|
init_MultilineInput();
|
|
8568
8815
|
init_ChatLayout();
|
|
8569
8816
|
init_StatusBar();
|
|
@@ -8572,12 +8819,12 @@ var init_app = __esm({
|
|
|
8572
8819
|
init_ProfileForm();
|
|
8573
8820
|
init_AskUserModal();
|
|
8574
8821
|
init_secrets();
|
|
8575
|
-
init_ai();
|
|
8822
|
+
await init_ai();
|
|
8576
8823
|
init_settings();
|
|
8577
8824
|
init_history();
|
|
8578
8825
|
init_ResumeModal();
|
|
8579
8826
|
init_MemoryModal();
|
|
8580
|
-
init_UpdateProcessor();
|
|
8827
|
+
await init_UpdateProcessor();
|
|
8581
8828
|
init_revert();
|
|
8582
8829
|
init_RevertModal();
|
|
8583
8830
|
init_usage();
|
|
@@ -8585,7 +8832,7 @@ var init_app = __esm({
|
|
|
8585
8832
|
init_arg_parser();
|
|
8586
8833
|
init_paths();
|
|
8587
8834
|
init_terminal();
|
|
8588
|
-
init_exec_command();
|
|
8835
|
+
await init_exec_command();
|
|
8589
8836
|
init_setup();
|
|
8590
8837
|
init_text();
|
|
8591
8838
|
SESSION_START_TIME = Date.now();
|
|
@@ -8596,6 +8843,17 @@ var init_app = __esm({
|
|
|
8596
8843
|
packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
|
|
8597
8844
|
versionFluxflow = packageJson.version;
|
|
8598
8845
|
updatedOn = packageJson.date || "2026-05-20";
|
|
8846
|
+
SPINNER_FRAMES2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
8847
|
+
StatusSpinner = () => {
|
|
8848
|
+
const [tick, setTick] = useState10(0);
|
|
8849
|
+
useEffect7(() => {
|
|
8850
|
+
const interval = setInterval(() => {
|
|
8851
|
+
setTick((t) => (t + 1) % 1e3);
|
|
8852
|
+
}, 33);
|
|
8853
|
+
return () => clearInterval(interval);
|
|
8854
|
+
}, []);
|
|
8855
|
+
return /* @__PURE__ */ React13.createElement(Text13, { color: "magenta" }, SPINNER_FRAMES2[Math.floor(tick / 3) % SPINNER_FRAMES2.length]);
|
|
8856
|
+
};
|
|
8599
8857
|
ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React13.createElement(Box13, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React13.createElement(Text13, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React13.createElement(Box13, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React13.createElement(Text13, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React13.createElement(Box13, { marginTop: 0 }, /* @__PURE__ */ React13.createElement(
|
|
8600
8858
|
CommandMenu,
|
|
8601
8859
|
{
|
|
@@ -8723,12 +8981,12 @@ var init_app = __esm({
|
|
|
8723
8981
|
});
|
|
8724
8982
|
|
|
8725
8983
|
// src/cli.jsx
|
|
8726
|
-
import { spawn as
|
|
8984
|
+
import { spawn as spawn3 } from "child_process";
|
|
8727
8985
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
8728
8986
|
var HEAP_LIMIT = 4096;
|
|
8729
8987
|
var isBundled = fileURLToPath2(import.meta.url).endsWith(".js");
|
|
8730
8988
|
if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-size"))) {
|
|
8731
|
-
const cp =
|
|
8989
|
+
const cp = spawn3(process.execPath, [
|
|
8732
8990
|
`--max-old-space-size=${HEAP_LIMIT}`,
|
|
8733
8991
|
fileURLToPath2(import.meta.url),
|
|
8734
8992
|
...process.argv.slice(2)
|
|
@@ -8737,7 +8995,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
|
|
|
8737
8995
|
} else {
|
|
8738
8996
|
const { default: React14 } = await import("react");
|
|
8739
8997
|
const { render } = await import("ink");
|
|
8740
|
-
const { default: App2 } = await
|
|
8998
|
+
const { default: App2 } = await init_app().then(() => app_exports);
|
|
8741
8999
|
process.env.NODE_NO_WARNINGS = "1";
|
|
8742
9000
|
const silentPatterns = [
|
|
8743
9001
|
"cuimp",
|