fluxflow-cli 1.18.4 → 1.18.6
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 +783 -613
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -97,7 +97,7 @@ var init_MultilineInput = __esm({
|
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
99
|
return {
|
|
100
|
-
preCursor: [{ value: showCursor && focus ? "
|
|
100
|
+
preCursor: [{ value: showCursor && focus ? " " : "", 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 ? " " : "", 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: showCursor && focus ? "
|
|
138
|
+
{ value: showCursor && focus ? " " : "", type: "cursor" }
|
|
139
139
|
],
|
|
140
140
|
postCursor: [
|
|
141
141
|
{
|
|
@@ -191,7 +191,7 @@ var init_MultilineInput = __esm({
|
|
|
191
191
|
...textStyle,
|
|
192
192
|
color: "cyan",
|
|
193
193
|
bold: true,
|
|
194
|
-
inverse:
|
|
194
|
+
inverse: true
|
|
195
195
|
};
|
|
196
196
|
default:
|
|
197
197
|
return textStyle;
|
|
@@ -450,7 +450,7 @@ var init_TerminalBox = __esm({
|
|
|
450
450
|
};
|
|
451
451
|
const cleanOutput = isPty ? processPTY(output) : (output || "").replace(/\r\n/g, "\n");
|
|
452
452
|
const displayOutput = isPty ? cleanOutput : cleanOutput ? wrapText(cleanOutput, columns - 6) : "";
|
|
453
|
-
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)")));
|
|
453
|
+
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 }, isFocused ? "Press TAB to unfocus, then double-press ESC to terminate." : "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)")));
|
|
454
454
|
});
|
|
455
455
|
}
|
|
456
456
|
});
|
|
@@ -997,6 +997,635 @@ var init_CommandMenu = __esm({
|
|
|
997
997
|
}
|
|
998
998
|
});
|
|
999
999
|
|
|
1000
|
+
// src/utils/arg_parser.js
|
|
1001
|
+
var parseArgs;
|
|
1002
|
+
var init_arg_parser = __esm({
|
|
1003
|
+
"src/utils/arg_parser.js"() {
|
|
1004
|
+
parseArgs = (argsString) => {
|
|
1005
|
+
const args = {};
|
|
1006
|
+
if (!argsString) return args;
|
|
1007
|
+
let i = 0;
|
|
1008
|
+
while (i < argsString.length) {
|
|
1009
|
+
while (i < argsString.length && /[\s,]/.test(argsString[i])) i++;
|
|
1010
|
+
if (i >= argsString.length) break;
|
|
1011
|
+
let keyMatch = argsString.substring(i).match(/^(\w+)\s*=\s*/);
|
|
1012
|
+
if (!keyMatch) {
|
|
1013
|
+
i++;
|
|
1014
|
+
continue;
|
|
1015
|
+
}
|
|
1016
|
+
const key = keyMatch[1];
|
|
1017
|
+
i += keyMatch[0].length;
|
|
1018
|
+
let value = "";
|
|
1019
|
+
if (i < argsString.length && (argsString[i] === '"' || argsString[i] === "'" || argsString[i] === "`")) {
|
|
1020
|
+
const quote = argsString[i];
|
|
1021
|
+
i++;
|
|
1022
|
+
let start = i;
|
|
1023
|
+
let end = -1;
|
|
1024
|
+
let searchIndex = i;
|
|
1025
|
+
while (searchIndex < argsString.length) {
|
|
1026
|
+
let qIdx = argsString.indexOf(quote, searchIndex);
|
|
1027
|
+
if (qIdx === -1) break;
|
|
1028
|
+
if (argsString[qIdx - 1] === "\\" && argsString[qIdx - 2] !== "\\") {
|
|
1029
|
+
searchIndex = qIdx + 1;
|
|
1030
|
+
continue;
|
|
1031
|
+
}
|
|
1032
|
+
const after = argsString.substring(qIdx + 1).trim();
|
|
1033
|
+
const isLogicalEnd = after === "" || // End of entire string
|
|
1034
|
+
after.startsWith(",") || // Next argument separator
|
|
1035
|
+
/^(\w+)\s*=/.test(after) || // Next argument key=
|
|
1036
|
+
after.startsWith(")") && (after.length === 1 || /^\)\s*([,\]\s]|tool:)/i.test(after));
|
|
1037
|
+
if (isLogicalEnd) {
|
|
1038
|
+
end = qIdx;
|
|
1039
|
+
break;
|
|
1040
|
+
}
|
|
1041
|
+
searchIndex = qIdx + 1;
|
|
1042
|
+
}
|
|
1043
|
+
if (end !== -1) {
|
|
1044
|
+
value = argsString.substring(start, end);
|
|
1045
|
+
i = end + 1;
|
|
1046
|
+
} else {
|
|
1047
|
+
value = argsString.substring(start);
|
|
1048
|
+
i = argsString.length;
|
|
1049
|
+
}
|
|
1050
|
+
const isPathKey = key.toLowerCase().includes("path") || ["dest", "source", "to", "from"].includes(key.toLowerCase());
|
|
1051
|
+
if (isPathKey) {
|
|
1052
|
+
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\`/g, "`").replace(/\\\\/g, "\\");
|
|
1053
|
+
} else {
|
|
1054
|
+
try {
|
|
1055
|
+
if (value.includes("\\")) {
|
|
1056
|
+
const surgicalValue = value.replace(/(^|[^\\])"/g, '$1\\"');
|
|
1057
|
+
value = JSON.parse(`"${surgicalValue.replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`);
|
|
1058
|
+
}
|
|
1059
|
+
} catch (e) {
|
|
1060
|
+
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\`/g, "`").replace(/\\\\/g, "\\").replace(/\\n/g, "\n");
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
} else if (i < argsString.length && argsString[i] === "[") {
|
|
1064
|
+
let balance = 0;
|
|
1065
|
+
let inString = null;
|
|
1066
|
+
let start = i;
|
|
1067
|
+
let end = -1;
|
|
1068
|
+
for (let j = i; j < argsString.length; j++) {
|
|
1069
|
+
const char = argsString[j];
|
|
1070
|
+
if (!inString && (char === '"' || char === "'" || char === "`")) {
|
|
1071
|
+
inString = char;
|
|
1072
|
+
} else if (inString && char === inString && argsString[j - 1] !== "\\") {
|
|
1073
|
+
inString = null;
|
|
1074
|
+
}
|
|
1075
|
+
if (!inString) {
|
|
1076
|
+
if (char === "[") balance++;
|
|
1077
|
+
else if (char === "]") balance--;
|
|
1078
|
+
if (balance === 0) {
|
|
1079
|
+
end = j;
|
|
1080
|
+
break;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
}
|
|
1084
|
+
if (end !== -1) {
|
|
1085
|
+
value = argsString.substring(start, end + 1);
|
|
1086
|
+
i = end + 1;
|
|
1087
|
+
try {
|
|
1088
|
+
let normalized = value.trim();
|
|
1089
|
+
if (normalized.startsWith("'") || normalized.includes("'")) {
|
|
1090
|
+
}
|
|
1091
|
+
} catch (e) {
|
|
1092
|
+
}
|
|
1093
|
+
} else {
|
|
1094
|
+
value = argsString.substring(start);
|
|
1095
|
+
i = argsString.length;
|
|
1096
|
+
}
|
|
1097
|
+
} else {
|
|
1098
|
+
let endMatch = argsString.substring(i).match(/([^,\s\)]+)/);
|
|
1099
|
+
if (endMatch) {
|
|
1100
|
+
value = endMatch[1];
|
|
1101
|
+
i += value.length;
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
if (value === "true") value = true;
|
|
1105
|
+
else if (value === "false") value = false;
|
|
1106
|
+
else if (typeof value === "string" && !isNaN(value) && value.trim() !== "") value = Number(value);
|
|
1107
|
+
if (typeof value === "string" && (key.toLowerCase().includes("path") || ["dest", "source", "to", "from"].includes(key.toLowerCase()))) {
|
|
1108
|
+
value = value.replace(/\x0C/g, "\\f").replace(/\x0D/g, "\\r").replace(/\x0B/g, "\\v").replace(/\x08/g, "\\b");
|
|
1109
|
+
}
|
|
1110
|
+
args[key] = value;
|
|
1111
|
+
}
|
|
1112
|
+
return args;
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
});
|
|
1116
|
+
|
|
1117
|
+
// src/data/main_tools.js
|
|
1118
|
+
import { execSync } from "child_process";
|
|
1119
|
+
var _isPsAvailable, isPsAvailable, TOOL_PROTOCOL;
|
|
1120
|
+
var init_main_tools = __esm({
|
|
1121
|
+
"src/data/main_tools.js"() {
|
|
1122
|
+
_isPsAvailable = null;
|
|
1123
|
+
isPsAvailable = () => {
|
|
1124
|
+
if (process.platform !== "win32") return false;
|
|
1125
|
+
if (_isPsAvailable !== null) return _isPsAvailable;
|
|
1126
|
+
try {
|
|
1127
|
+
execSync('powershell.exe -NoProfile -Command "exit"', { stdio: "ignore" });
|
|
1128
|
+
_isPsAvailable = true;
|
|
1129
|
+
} catch (e) {
|
|
1130
|
+
_isPsAvailable = false;
|
|
1131
|
+
}
|
|
1132
|
+
return _isPsAvailable;
|
|
1133
|
+
};
|
|
1134
|
+
TOOL_PROTOCOL = (mode, osDetected) => `
|
|
1135
|
+
-- TOOL DEFINITIONS --
|
|
1136
|
+
Access to internal tools. To call a tool, MUST use the exact syntax on a new line: [tool:functions.ToolName(args)]
|
|
1137
|
+
STRICT POLICY
|
|
1138
|
+
- **MAX 3 TOOL CALLS PER TURN. Next Turn, verify results, plan next**${mode === "Flux" ? "\n- **File Tools >> Code in chat**" : ""}
|
|
1139
|
+
|
|
1140
|
+
- COMMUNICATION TOOLS -
|
|
1141
|
+
1. [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish
|
|
1142
|
+
Suggest best options; don't ask for preferences
|
|
1143
|
+
|
|
1144
|
+
- WEB TOOLS -
|
|
1145
|
+
1. [tool:functions.WebSearch(query="...", limit=number)]. Limit 3-10. Proactive use for unknown topics${mode === "Flux" ? " or docs" : ""}
|
|
1146
|
+
2. [tool:functions.WebScrape(url="...")]. Visit URL
|
|
1147
|
+
|
|
1148
|
+
${mode === "Flux" ? `- PROJECT TOOLS (path = relative to CWD) -
|
|
1149
|
+
1. [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. Supports images/docs. User gives image/doc: VIEW FIRST
|
|
1150
|
+
2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
|
|
1151
|
+
3. [tool:functions.PatchFile(path="...", replaceContent1="exact string", newContent1="...", ...MAX 8)]. Surgical Patch. Unsure? ReadFile > guessing. Multiple blocks same file? Use replaceContent2, newContent2 etc.
|
|
1152
|
+
4. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile >> WriteFile. Verify Imports
|
|
1153
|
+
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
|
|
1154
|
+
6. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? "WINDOWS POWERSHELL ONLY" : "WINDOWS CMD" : "Bash"} command. Destructive/Irreversible ops -> Ask user
|
|
1155
|
+
7. [tool:functions.GenerateImage(path="... png", prompt="detailed", ratio="16:9, 9:16, 1:1")]. Usage: Mockups, PDF thumbnails, any visual content
|
|
1156
|
+
8. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout (100vh/vw)
|
|
1157
|
+
9. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document
|
|
1158
|
+
|
|
1159
|
+
- VERIFY TOOL RESULT CONTENTS. Fix errors. No hallucinations
|
|
1160
|
+
|
|
1161
|
+
- Escape quotes: \\" for code strings
|
|
1162
|
+
- Literal escapes: Double-escape sequences (e.g., \\\\n, \\\\t)
|
|
1163
|
+
- File structure: Real newlines for code formatting`.trim() : `
|
|
1164
|
+
- FILE TOOLS ARE NOT AVAILABLE IN FLOW (Tell user,\` /mode flux\` if needed)`.trim()}
|
|
1165
|
+
|
|
1166
|
+
- Results: Passed as [TOOL RESULT] (system priority)
|
|
1167
|
+
- MAX Tool call stack: STRICTLY 3 per turn`.trim();
|
|
1168
|
+
}
|
|
1169
|
+
});
|
|
1170
|
+
|
|
1171
|
+
// src/tools/exec_command.js
|
|
1172
|
+
import { spawn } from "child_process";
|
|
1173
|
+
var pty, isPtyAvailable, stripAnsi, activeChildProcess, isActiveCommandPty, writeToActiveCommand, terminateActiveCommand, adjustWindowsCommand, exec_command, runStandardSpawn;
|
|
1174
|
+
var init_exec_command = __esm({
|
|
1175
|
+
async "src/tools/exec_command.js"() {
|
|
1176
|
+
init_arg_parser();
|
|
1177
|
+
init_main_tools();
|
|
1178
|
+
pty = null;
|
|
1179
|
+
try {
|
|
1180
|
+
const ptyModule = await import("node-pty");
|
|
1181
|
+
pty = ptyModule.default || ptyModule;
|
|
1182
|
+
} catch (err) {
|
|
1183
|
+
}
|
|
1184
|
+
isPtyAvailable = !!pty;
|
|
1185
|
+
stripAnsi = (str) => {
|
|
1186
|
+
if (typeof str !== "string") return str;
|
|
1187
|
+
return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
|
1188
|
+
};
|
|
1189
|
+
activeChildProcess = null;
|
|
1190
|
+
isActiveCommandPty = false;
|
|
1191
|
+
writeToActiveCommand = (data) => {
|
|
1192
|
+
try {
|
|
1193
|
+
if (activeChildProcess) {
|
|
1194
|
+
if (isActiveCommandPty && typeof activeChildProcess.write === "function") {
|
|
1195
|
+
activeChildProcess.write(data);
|
|
1196
|
+
} else if (activeChildProcess.stdin && activeChildProcess.stdin.writable) {
|
|
1197
|
+
activeChildProcess.stdin.write(data);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
} catch (err) {
|
|
1201
|
+
}
|
|
1202
|
+
};
|
|
1203
|
+
terminateActiveCommand = () => {
|
|
1204
|
+
if (activeChildProcess) {
|
|
1205
|
+
try {
|
|
1206
|
+
if (isActiveCommandPty && typeof activeChildProcess.destroy === "function") {
|
|
1207
|
+
activeChildProcess.destroy();
|
|
1208
|
+
} else if (typeof activeChildProcess.kill === "function") {
|
|
1209
|
+
activeChildProcess.kill("SIGKILL");
|
|
1210
|
+
}
|
|
1211
|
+
} catch (err) {
|
|
1212
|
+
}
|
|
1213
|
+
activeChildProcess = null;
|
|
1214
|
+
isActiveCommandPty = false;
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
adjustWindowsCommand = (command, usePowerShell = false) => {
|
|
1218
|
+
if (process.platform !== "win32") return command;
|
|
1219
|
+
const tokens = [];
|
|
1220
|
+
let current = "";
|
|
1221
|
+
let inQuote = null;
|
|
1222
|
+
let isEscaped = false;
|
|
1223
|
+
for (let i = 0; i < command.length; i++) {
|
|
1224
|
+
const char = command[i];
|
|
1225
|
+
if (isEscaped) {
|
|
1226
|
+
current += char;
|
|
1227
|
+
isEscaped = false;
|
|
1228
|
+
continue;
|
|
1229
|
+
}
|
|
1230
|
+
if (char === "\\") {
|
|
1231
|
+
if (command[i + 1] === " ") {
|
|
1232
|
+
current += " ";
|
|
1233
|
+
i++;
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
current += char;
|
|
1237
|
+
isEscaped = true;
|
|
1238
|
+
continue;
|
|
1239
|
+
}
|
|
1240
|
+
if (inQuote) {
|
|
1241
|
+
if (char === inQuote) {
|
|
1242
|
+
inQuote = null;
|
|
1243
|
+
}
|
|
1244
|
+
current += char;
|
|
1245
|
+
} else {
|
|
1246
|
+
if (char === '"' || char === "'") {
|
|
1247
|
+
inQuote = char;
|
|
1248
|
+
current += char;
|
|
1249
|
+
} else if (char === ";" && !current.includes("://")) {
|
|
1250
|
+
if (current.length > 0) {
|
|
1251
|
+
tokens.push(current);
|
|
1252
|
+
current = "";
|
|
1253
|
+
}
|
|
1254
|
+
tokens.push(usePowerShell ? ";" : "&");
|
|
1255
|
+
} else if (char === "|" && !current.includes("://")) {
|
|
1256
|
+
if (current.length > 0) {
|
|
1257
|
+
tokens.push(current);
|
|
1258
|
+
current = "";
|
|
1259
|
+
}
|
|
1260
|
+
tokens.push("|");
|
|
1261
|
+
} else if (/\s/.test(char)) {
|
|
1262
|
+
if (current.length > 0) {
|
|
1263
|
+
tokens.push(current);
|
|
1264
|
+
current = "";
|
|
1265
|
+
}
|
|
1266
|
+
} else {
|
|
1267
|
+
current += char;
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
if (current.length > 0) {
|
|
1272
|
+
tokens.push(current);
|
|
1273
|
+
}
|
|
1274
|
+
const looksLikePath = (str) => {
|
|
1275
|
+
if (!str.includes("/")) return false;
|
|
1276
|
+
if (/^(https?|file|ftp):\/\//i.test(str)) return false;
|
|
1277
|
+
if (str.startsWith("/") && (str.match(/\//g) || []).length === 1) {
|
|
1278
|
+
return false;
|
|
1279
|
+
}
|
|
1280
|
+
if (/\s\/|\/\s/.test(str)) return false;
|
|
1281
|
+
if (/[\(\)\{\}\;\<\>\=\'\"]/.test(str)) return false;
|
|
1282
|
+
return true;
|
|
1283
|
+
};
|
|
1284
|
+
const translatedTokens = [];
|
|
1285
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
1286
|
+
const token = tokens[i];
|
|
1287
|
+
if (token === "mkdir" && usePowerShell && isPsAvailable()) {
|
|
1288
|
+
const paths = [];
|
|
1289
|
+
let j = i + 1;
|
|
1290
|
+
while (j < tokens.length) {
|
|
1291
|
+
const nextToken = tokens[j];
|
|
1292
|
+
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
1293
|
+
if (controlOperators.includes(nextToken)) {
|
|
1294
|
+
break;
|
|
1295
|
+
}
|
|
1296
|
+
if (nextToken !== "-p" && nextToken !== "--parents" && nextToken !== "-v" && nextToken !== "--verbose") {
|
|
1297
|
+
paths.push(nextToken);
|
|
1298
|
+
}
|
|
1299
|
+
j++;
|
|
1300
|
+
}
|
|
1301
|
+
if (paths.length > 0) {
|
|
1302
|
+
const processedPaths = paths.map((p) => {
|
|
1303
|
+
const unquoted = p.replace(/^['"]|['"]$/g, "");
|
|
1304
|
+
let newPath = p;
|
|
1305
|
+
if (looksLikePath(unquoted)) {
|
|
1306
|
+
newPath = p.replace(/\//g, "\\");
|
|
1307
|
+
}
|
|
1308
|
+
return newPath;
|
|
1309
|
+
});
|
|
1310
|
+
translatedTokens.push("New-Item", "-ItemType", "Directory", "-Force", "-Path", processedPaths.join(","));
|
|
1311
|
+
} else {
|
|
1312
|
+
translatedTokens.push("New-Item", "-ItemType", "Directory", "-Force");
|
|
1313
|
+
}
|
|
1314
|
+
i = j - 1;
|
|
1315
|
+
continue;
|
|
1316
|
+
}
|
|
1317
|
+
if (token === "rm" && usePowerShell && isPsAvailable()) {
|
|
1318
|
+
const paths = [];
|
|
1319
|
+
let recurse = false;
|
|
1320
|
+
let force = false;
|
|
1321
|
+
let j = i + 1;
|
|
1322
|
+
while (j < tokens.length) {
|
|
1323
|
+
const nextToken = tokens[j];
|
|
1324
|
+
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
1325
|
+
if (controlOperators.includes(nextToken)) {
|
|
1326
|
+
break;
|
|
1327
|
+
}
|
|
1328
|
+
if (nextToken === "-rf" || nextToken === "-fr") {
|
|
1329
|
+
recurse = true;
|
|
1330
|
+
force = true;
|
|
1331
|
+
} else if (nextToken === "-r" || nextToken === "-R" || nextToken === "--recursive") {
|
|
1332
|
+
recurse = true;
|
|
1333
|
+
} else if (nextToken === "-f" || nextToken === "--force") {
|
|
1334
|
+
force = true;
|
|
1335
|
+
} else {
|
|
1336
|
+
paths.push(nextToken);
|
|
1337
|
+
}
|
|
1338
|
+
j++;
|
|
1339
|
+
}
|
|
1340
|
+
const args = ["Remove-Item"];
|
|
1341
|
+
if (recurse) args.push("-Recurse");
|
|
1342
|
+
if (force) args.push("-Force");
|
|
1343
|
+
if (paths.length > 0) {
|
|
1344
|
+
const processedPaths = paths.map((p) => {
|
|
1345
|
+
const unquoted = p.replace(/^['"]|['"]$/g, "");
|
|
1346
|
+
let newPath = p;
|
|
1347
|
+
if (looksLikePath(unquoted)) {
|
|
1348
|
+
newPath = p.replace(/\//g, "\\");
|
|
1349
|
+
}
|
|
1350
|
+
return newPath;
|
|
1351
|
+
});
|
|
1352
|
+
args.push("-Path", processedPaths.join(","));
|
|
1353
|
+
}
|
|
1354
|
+
translatedTokens.push(...args);
|
|
1355
|
+
i = j - 1;
|
|
1356
|
+
continue;
|
|
1357
|
+
}
|
|
1358
|
+
if (token === "cp" && usePowerShell && isPsAvailable()) {
|
|
1359
|
+
const paths = [];
|
|
1360
|
+
let recurse = false;
|
|
1361
|
+
let force = false;
|
|
1362
|
+
let j = i + 1;
|
|
1363
|
+
while (j < tokens.length) {
|
|
1364
|
+
const nextToken = tokens[j];
|
|
1365
|
+
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
1366
|
+
if (controlOperators.includes(nextToken)) {
|
|
1367
|
+
break;
|
|
1368
|
+
}
|
|
1369
|
+
if (nextToken === "-r" || nextToken === "-R" || nextToken === "--recursive") {
|
|
1370
|
+
recurse = true;
|
|
1371
|
+
} else if (nextToken === "-f" || nextToken === "--force") {
|
|
1372
|
+
force = true;
|
|
1373
|
+
} else {
|
|
1374
|
+
paths.push(nextToken);
|
|
1375
|
+
}
|
|
1376
|
+
j++;
|
|
1377
|
+
}
|
|
1378
|
+
const args = ["Copy-Item"];
|
|
1379
|
+
if (recurse) args.push("-Recurse");
|
|
1380
|
+
if (force) args.push("-Force");
|
|
1381
|
+
if (paths.length > 0) {
|
|
1382
|
+
const processedPaths = paths.map((p) => {
|
|
1383
|
+
const unquoted = p.replace(/^['"]|['"]$/g, "");
|
|
1384
|
+
let newPath = p;
|
|
1385
|
+
if (looksLikePath(unquoted)) {
|
|
1386
|
+
newPath = p.replace(/\//g, "\\");
|
|
1387
|
+
}
|
|
1388
|
+
return newPath;
|
|
1389
|
+
});
|
|
1390
|
+
if (processedPaths.length > 1) {
|
|
1391
|
+
const dest = processedPaths.pop();
|
|
1392
|
+
args.push("-Path", processedPaths.join(","), "-Destination", dest);
|
|
1393
|
+
} else {
|
|
1394
|
+
args.push("-Path", processedPaths[0]);
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1397
|
+
translatedTokens.push(...args);
|
|
1398
|
+
i = j - 1;
|
|
1399
|
+
continue;
|
|
1400
|
+
}
|
|
1401
|
+
if (token === "touch" && usePowerShell && isPsAvailable()) {
|
|
1402
|
+
const paths = [];
|
|
1403
|
+
let j = i + 1;
|
|
1404
|
+
while (j < tokens.length) {
|
|
1405
|
+
const nextToken = tokens[j];
|
|
1406
|
+
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
1407
|
+
if (controlOperators.includes(nextToken)) {
|
|
1408
|
+
break;
|
|
1409
|
+
}
|
|
1410
|
+
paths.push(nextToken);
|
|
1411
|
+
j++;
|
|
1412
|
+
}
|
|
1413
|
+
if (paths.length > 0) {
|
|
1414
|
+
const processedPaths = paths.map((p) => {
|
|
1415
|
+
const unquoted = p.replace(/^['"]|['"]$/g, "");
|
|
1416
|
+
let newPath = p;
|
|
1417
|
+
if (looksLikePath(unquoted)) {
|
|
1418
|
+
newPath = p.replace(/\//g, "\\");
|
|
1419
|
+
}
|
|
1420
|
+
return newPath;
|
|
1421
|
+
});
|
|
1422
|
+
const psTouch = `(${processedPaths.join(", ")}) | ForEach-Object { if (Test-Path $_) { (Get-Item $_).LastWriteTime = [System.DateTime]::Now } else { $null | Out-File -FilePath $_ } }`;
|
|
1423
|
+
translatedTokens.push(psTouch);
|
|
1424
|
+
}
|
|
1425
|
+
i = j - 1;
|
|
1426
|
+
continue;
|
|
1427
|
+
}
|
|
1428
|
+
if (token === "|" && tokens[i + 1] === "tee") {
|
|
1429
|
+
if (tokens[i + 2] === "-a") {
|
|
1430
|
+
translatedTokens.push(">>");
|
|
1431
|
+
i += 2;
|
|
1432
|
+
} else {
|
|
1433
|
+
translatedTokens.push(">");
|
|
1434
|
+
i += 1;
|
|
1435
|
+
}
|
|
1436
|
+
continue;
|
|
1437
|
+
}
|
|
1438
|
+
if (token === "|" && tokens[i + 1] === "cat" && tokens[i + 2] === ">") {
|
|
1439
|
+
translatedTokens.push(">");
|
|
1440
|
+
i += 2;
|
|
1441
|
+
continue;
|
|
1442
|
+
}
|
|
1443
|
+
if (token === "|") {
|
|
1444
|
+
const nextToken = tokens[i + 1];
|
|
1445
|
+
if (nextToken) {
|
|
1446
|
+
const nextUnquoted = nextToken.replace(/^['"]|['"]$/g, "");
|
|
1447
|
+
const isWritableFile = /\.(txt|md|json|log|csv|html|css|py|js|xml|yaml|yml|pdf|docx|pptx|xlsx)$/i.test(nextUnquoted);
|
|
1448
|
+
if (looksLikePath(nextUnquoted) && isWritableFile) {
|
|
1449
|
+
translatedTokens.push(">");
|
|
1450
|
+
continue;
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
}
|
|
1454
|
+
translatedTokens.push(token);
|
|
1455
|
+
}
|
|
1456
|
+
let inEchoArguments = false;
|
|
1457
|
+
const processedTokens = translatedTokens.map((token) => {
|
|
1458
|
+
if (token === "echo") {
|
|
1459
|
+
inEchoArguments = true;
|
|
1460
|
+
return token;
|
|
1461
|
+
}
|
|
1462
|
+
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
1463
|
+
if (controlOperators.includes(token)) {
|
|
1464
|
+
inEchoArguments = false;
|
|
1465
|
+
}
|
|
1466
|
+
const hasOuterQuotes = /^['"]|['"]$/.test(token);
|
|
1467
|
+
let processed = token;
|
|
1468
|
+
if (inEchoArguments && hasOuterQuotes) {
|
|
1469
|
+
processed = token.replace(/^['"]|['"]$/g, "");
|
|
1470
|
+
}
|
|
1471
|
+
const currentHasOuterQuotes = /^['"]|['"]$/.test(processed);
|
|
1472
|
+
const unquoted = processed.replace(/^['"]|['"]$/g, "");
|
|
1473
|
+
if (looksLikePath(unquoted)) {
|
|
1474
|
+
processed = processed.replace(/\//g, "\\");
|
|
1475
|
+
}
|
|
1476
|
+
const finalUnquoted = processed.replace(/^['"]|['"]$/g, "");
|
|
1477
|
+
if (finalUnquoted.includes(" ") && !currentHasOuterQuotes) {
|
|
1478
|
+
processed = `"${finalUnquoted}"`;
|
|
1479
|
+
}
|
|
1480
|
+
return processed;
|
|
1481
|
+
});
|
|
1482
|
+
return processedTokens.join(" ");
|
|
1483
|
+
};
|
|
1484
|
+
exec_command = async (args, options = {}) => {
|
|
1485
|
+
const { command: rawCommand } = parseArgs(args);
|
|
1486
|
+
const { onChunk } = options;
|
|
1487
|
+
if (!rawCommand) return 'ERROR: Missing "command" argument for exec_command.';
|
|
1488
|
+
const isWin = process.platform === "win32";
|
|
1489
|
+
const systemSettings = options.systemSettings || {};
|
|
1490
|
+
const netEnv = {};
|
|
1491
|
+
if (systemSettings.networkAccess === false) {
|
|
1492
|
+
netEnv.HTTP_PROXY = "http://127.0.0.1:9999";
|
|
1493
|
+
netEnv.HTTPS_PROXY = "http://127.0.0.1:9999";
|
|
1494
|
+
netEnv.ALL_PROXY = "socks5://127.0.0.1:9999";
|
|
1495
|
+
netEnv.http_proxy = "http://127.0.0.1:9999";
|
|
1496
|
+
netEnv.https_proxy = "http://127.0.0.1:9999";
|
|
1497
|
+
netEnv.all_proxy = "socks5://127.0.0.1:9999";
|
|
1498
|
+
netEnv.NO_PROXY = "localhost,127.0.0.1";
|
|
1499
|
+
}
|
|
1500
|
+
return new Promise((resolve) => {
|
|
1501
|
+
const attempt = (usePowerShell) => {
|
|
1502
|
+
const command = adjustWindowsCommand(rawCommand, usePowerShell);
|
|
1503
|
+
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
1504
|
+
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
1505
|
+
if (pty) {
|
|
1506
|
+
try {
|
|
1507
|
+
const ptyProcess = pty.spawn(shell, shellArgs, {
|
|
1508
|
+
name: "xterm-256color",
|
|
1509
|
+
cols: options.cols || 120,
|
|
1510
|
+
rows: options.rows || 30,
|
|
1511
|
+
cwd: process.cwd(),
|
|
1512
|
+
env: {
|
|
1513
|
+
...process.env,
|
|
1514
|
+
CI: "false",
|
|
1515
|
+
TERM: "xterm-256color",
|
|
1516
|
+
FORCE_COLOR: "1",
|
|
1517
|
+
...netEnv
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
activeChildProcess = ptyProcess;
|
|
1521
|
+
isActiveCommandPty = true;
|
|
1522
|
+
let output = "";
|
|
1523
|
+
ptyProcess.onData((data) => {
|
|
1524
|
+
output += data;
|
|
1525
|
+
if (onChunk) onChunk(data);
|
|
1526
|
+
});
|
|
1527
|
+
ptyProcess.onExit(({ exitCode }) => {
|
|
1528
|
+
activeChildProcess = null;
|
|
1529
|
+
const normalizedOutput = (output || "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1530
|
+
const finalOutput = stripAnsi(normalizedOutput) || "Command executed with no output.";
|
|
1531
|
+
if (exitCode !== 0) {
|
|
1532
|
+
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${exitCode}].
|
|
1533
|
+
|
|
1534
|
+
${finalOutput}`);
|
|
1535
|
+
} else {
|
|
1536
|
+
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
1537
|
+
|
|
1538
|
+
${finalOutput}`);
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
return true;
|
|
1542
|
+
} catch (err) {
|
|
1543
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
1544
|
+
return false;
|
|
1545
|
+
}
|
|
1546
|
+
runStandardSpawn(resolve, command, rawCommand, netEnv, onChunk, usePowerShell);
|
|
1547
|
+
return true;
|
|
1548
|
+
}
|
|
1549
|
+
} else {
|
|
1550
|
+
runStandardSpawn(resolve, command, rawCommand, netEnv, onChunk, usePowerShell);
|
|
1551
|
+
return true;
|
|
1552
|
+
}
|
|
1553
|
+
};
|
|
1554
|
+
if (isWin) {
|
|
1555
|
+
if (!attempt(true)) {
|
|
1556
|
+
attempt(false);
|
|
1557
|
+
}
|
|
1558
|
+
} else {
|
|
1559
|
+
attempt(false);
|
|
1560
|
+
}
|
|
1561
|
+
});
|
|
1562
|
+
};
|
|
1563
|
+
runStandardSpawn = (resolve, command, rawCommand, netEnv, onChunk, usePowerShell = true) => {
|
|
1564
|
+
const isWin = process.platform === "win32";
|
|
1565
|
+
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
1566
|
+
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
1567
|
+
const child = isWin ? spawn(shell, shellArgs, { cwd: process.cwd(), env: { ...process.env, ...netEnv } }) : spawn(command, {
|
|
1568
|
+
shell: true,
|
|
1569
|
+
cwd: process.cwd(),
|
|
1570
|
+
env: {
|
|
1571
|
+
...process.env,
|
|
1572
|
+
CI: "false",
|
|
1573
|
+
TERM: "xterm-256color",
|
|
1574
|
+
FORCE_COLOR: "1",
|
|
1575
|
+
...netEnv
|
|
1576
|
+
}
|
|
1577
|
+
});
|
|
1578
|
+
activeChildProcess = child;
|
|
1579
|
+
isActiveCommandPty = false;
|
|
1580
|
+
if (child.stdin) {
|
|
1581
|
+
child.stdin.on("error", () => {
|
|
1582
|
+
activeChildProcess = null;
|
|
1583
|
+
});
|
|
1584
|
+
}
|
|
1585
|
+
let stdout = "";
|
|
1586
|
+
let stderr = "";
|
|
1587
|
+
child.stdout.on("data", (data) => {
|
|
1588
|
+
const chunk = data.toString();
|
|
1589
|
+
stdout += chunk;
|
|
1590
|
+
if (onChunk) onChunk(chunk);
|
|
1591
|
+
});
|
|
1592
|
+
child.stderr.on("data", (data) => {
|
|
1593
|
+
const chunk = data.toString();
|
|
1594
|
+
stderr += chunk;
|
|
1595
|
+
if (onChunk) onChunk(chunk);
|
|
1596
|
+
});
|
|
1597
|
+
child.on("close", (code) => {
|
|
1598
|
+
activeChildProcess = null;
|
|
1599
|
+
const result = [];
|
|
1600
|
+
if (stdout) result.push(`STDOUT:
|
|
1601
|
+
${stdout}`);
|
|
1602
|
+
if (stderr) result.push(`STDERR:
|
|
1603
|
+
${stderr}`);
|
|
1604
|
+
if (code !== 0) result.push(`EXIT CODE: ${code}`);
|
|
1605
|
+
const rawOutput = result.join("\n\n") || "Command executed with no output.";
|
|
1606
|
+
const finalOutput = stripAnsi(rawOutput);
|
|
1607
|
+
if (code !== 0) {
|
|
1608
|
+
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${code}].
|
|
1609
|
+
|
|
1610
|
+
${finalOutput}`);
|
|
1611
|
+
} else {
|
|
1612
|
+
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
1613
|
+
|
|
1614
|
+
${finalOutput}`);
|
|
1615
|
+
}
|
|
1616
|
+
});
|
|
1617
|
+
child.on("error", (err) => {
|
|
1618
|
+
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
1619
|
+
const cmdCommand = adjustWindowsCommand(rawCommand, false);
|
|
1620
|
+
return runStandardSpawn(resolve, cmdCommand, rawCommand, netEnv, onChunk, false);
|
|
1621
|
+
}
|
|
1622
|
+
activeChildProcess = null;
|
|
1623
|
+
resolve(`ERROR: Failed to start command [${rawCommand}]: ${err.message}`);
|
|
1624
|
+
});
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
|
|
1000
1629
|
// src/components/SettingsMenu.jsx
|
|
1001
1630
|
import React6, { useState as useState3 } from "react";
|
|
1002
1631
|
import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
|
|
@@ -1230,6 +1859,8 @@ function SettingsMenu({
|
|
|
1230
1859
|
}
|
|
1231
1860
|
return "yellow";
|
|
1232
1861
|
}
|
|
1862
|
+
if (item2.status?.startsWith("\u2713")) return "green";
|
|
1863
|
+
if (item2.status?.startsWith("\u26A0")) return "yellow";
|
|
1233
1864
|
return item2.status === "ON" ? "green" : item2.status === "OFF" ? "red" : "yellow";
|
|
1234
1865
|
};
|
|
1235
1866
|
if (item.section && item.section !== lastSection) {
|
|
@@ -1264,6 +1895,11 @@ function SettingsMenu({
|
|
|
1264
1895
|
)), /* @__PURE__ */ React6.createElement(Text6, { color: "gray", dimColor: true, italic: true }, " Comma separated \u2022 Press Enter to save, Esc to cancel")))
|
|
1265
1896
|
);
|
|
1266
1897
|
});
|
|
1898
|
+
if (currentCatId === "other") {
|
|
1899
|
+
elements.push(
|
|
1900
|
+
/* @__PURE__ */ React6.createElement(Box6, { key: "pty-notice", marginTop: 4, paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: isPtyAvailable ? "green" : "yellow" }, isPtyAvailable ? "\u2713 Advance Interactive Terminal Supported" : "\u26A0 Interactive Terminal is Limited"))
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1267
1903
|
if (hasConflict) {
|
|
1268
1904
|
elements.push(
|
|
1269
1905
|
/* @__PURE__ */ React6.createElement(Box6, { key: "conflict-warning", marginTop: 1, paddingX: 1 }, /* @__PURE__ */ React6.createElement(Text6, { color: "red", dimColor: true, italic: true }, "* Conflicting commands will be ignored and defaulted to highest priority"))
|
|
@@ -1274,7 +1910,8 @@ function SettingsMenu({
|
|
|
1274
1910
|
}
|
|
1275
1911
|
var CATEGORIES, getActivePreset, truncateCSV;
|
|
1276
1912
|
var init_SettingsMenu = __esm({
|
|
1277
|
-
"src/components/SettingsMenu.jsx"() {
|
|
1913
|
+
async "src/components/SettingsMenu.jsx"() {
|
|
1914
|
+
await init_exec_command();
|
|
1278
1915
|
CATEGORIES = [
|
|
1279
1916
|
{ id: "memory", label: "\u{1F9E0} Memory", desc: "Manage system context & agent's memory" },
|
|
1280
1917
|
{ id: "security", label: "\u{1F512} Security", desc: "Configure permissions & data safety" },
|
|
@@ -1639,60 +2276,6 @@ var init_secrets = __esm({
|
|
|
1639
2276
|
}
|
|
1640
2277
|
});
|
|
1641
2278
|
|
|
1642
|
-
// src/data/main_tools.js
|
|
1643
|
-
import { execSync } from "child_process";
|
|
1644
|
-
var _isPsAvailable, isPsAvailable, TOOL_PROTOCOL;
|
|
1645
|
-
var init_main_tools = __esm({
|
|
1646
|
-
"src/data/main_tools.js"() {
|
|
1647
|
-
_isPsAvailable = null;
|
|
1648
|
-
isPsAvailable = () => {
|
|
1649
|
-
if (process.platform !== "win32") return false;
|
|
1650
|
-
if (_isPsAvailable !== null) return _isPsAvailable;
|
|
1651
|
-
try {
|
|
1652
|
-
execSync('powershell.exe -NoProfile -Command "exit"', { stdio: "ignore" });
|
|
1653
|
-
_isPsAvailable = true;
|
|
1654
|
-
} catch (e) {
|
|
1655
|
-
_isPsAvailable = false;
|
|
1656
|
-
}
|
|
1657
|
-
return _isPsAvailable;
|
|
1658
|
-
};
|
|
1659
|
-
TOOL_PROTOCOL = (mode, osDetected) => `
|
|
1660
|
-
-- TOOL DEFINITIONS --
|
|
1661
|
-
Access to internal tools. To call a tool, MUST use the exact syntax on a new line: [tool:functions.ToolName(args)]
|
|
1662
|
-
STRICT POLICY
|
|
1663
|
-
- **MAX 3 TOOL CALLS PER TURN. Next Turn, verify results, plan next**${mode === "Flux" ? "\n- **File Tools >> Code in chat**" : ""}
|
|
1664
|
-
|
|
1665
|
-
- COMMUNICATION TOOLS -
|
|
1666
|
-
1. [tool:functions.Ask(question="...", optionA="option::description", ...MAX 4)]. Ambiguity Resolution. Mandatory Triggers: Path Divergence, Security, Risk Mitigation. ask >> finish
|
|
1667
|
-
Suggest best options; don't ask for preferences
|
|
1668
|
-
|
|
1669
|
-
- WEB TOOLS -
|
|
1670
|
-
1. [tool:functions.WebSearch(query="...", limit=number)]. Limit 3-10. Proactive use for unknown topics${mode === "Flux" ? " or docs" : ""}
|
|
1671
|
-
2. [tool:functions.WebScrape(url="...")]. Visit URL
|
|
1672
|
-
|
|
1673
|
-
${mode === "Flux" ? `- PROJECT TOOLS (path = relative to CWD) -
|
|
1674
|
-
1. [tool:functions.ReadFile(path="...", startLine=number, endLine=number)]. Supports images/docs. User gives image/doc: VIEW FIRST
|
|
1675
|
-
2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
|
|
1676
|
-
3. [tool:functions.PatchFile(path="...", replaceContent1="exact string", newContent1="...", ...MAX 8)]. Surgical Patch. Unsure? ReadFile > guessing. Multiple blocks same file? Use replaceContent2, newContent2 etc.
|
|
1677
|
-
4. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile >> WriteFile. Verify Imports
|
|
1678
|
-
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
|
|
1679
|
-
6. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? "WINDOWS POWERSHELL" : "WINDOWS CMD" : "Bash"} command. Destructive/Irreversible ops -> Ask user
|
|
1680
|
-
7. [tool:functions.GenerateImage(path="... png", prompt="detailed", ratio="16:9, 9:16, 1:1")]. Usage: Mockups, PDF thumbnails, any visual content
|
|
1681
|
-
8. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout (100vh/vw)
|
|
1682
|
-
9. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word document
|
|
1683
|
-
|
|
1684
|
-
- VERIFY TOOL RESULT CONTENTS. Fix errors. No hallucinations
|
|
1685
|
-
|
|
1686
|
-
- Escape quotes: \\" for code strings
|
|
1687
|
-
- Literal escapes: Double-escape sequences (e.g., \\\\n, \\\\t)
|
|
1688
|
-
- File structure: Real newlines for code formatting`.trim() : `
|
|
1689
|
-
- FILE TOOLS ARE NOT AVAILABLE IN FLOW (Tell user,\` /mode flux\` if needed)`.trim()}
|
|
1690
|
-
|
|
1691
|
-
- Results: Passed as [TOOL RESULT] (system priority)
|
|
1692
|
-
- MAX Tool call stack: STRICTLY 3 per turn`.trim();
|
|
1693
|
-
}
|
|
1694
|
-
});
|
|
1695
|
-
|
|
1696
2279
|
// src/data/janitor_tools.js
|
|
1697
2280
|
var JANITOR_TOOLS_PROTOCOL;
|
|
1698
2281
|
var init_janitor_tools = __esm({
|
|
@@ -1804,6 +2387,14 @@ Check these first; These Files > Training Data. Safety rules apply
|
|
|
1804
2387
|
Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy${mode === "Flux" ? ", No Flirting, Respectful" : ", Friendly, Humorous, Sarcastic"}, CLI Agent
|
|
1805
2388
|
Mode: ${mode}${thinkingLevel !== "Fast" ? " (Thinking Mode)" : ""}. ${mode === "Flux" ? "Logical, Highly Detailed, Task-Driven. Prioritizes scalable file/folder structures, modular architecture, clean code abstractions, step-by-step execution. Industry standard latest coding practices/libraries, clean code, Double Check Imports, Client-Server Sync" : "Conversational, Concise"}
|
|
1806
2389
|
|
|
2390
|
+
-- AGENT LOOP RULES (PRIORITY: HIGH) --
|
|
2391
|
+
- **MUST END WITH [turn: continue] to continue loop OR [turn: finish] to END loop**
|
|
2392
|
+
- Tool Called? No post tool response until [turn: continue]
|
|
2393
|
+
- NEVER USE [turn: continue] [turn:finish] together
|
|
2394
|
+
|
|
2395
|
+
SYSTEM PRIORITY: [SYSTEM], [TOOL RESULT]
|
|
2396
|
+
HIGH PRIORITY: [STEERING HINT]
|
|
2397
|
+
|
|
1807
2398
|
-- THINKING RULES --
|
|
1808
2399
|
${thinkingConfig}
|
|
1809
2400
|
${thinkingLevel !== "Fast" ? `
|
|
@@ -1824,12 +2415,6 @@ ${projectContextBlock}
|
|
|
1824
2415
|
- GFM Supported
|
|
1825
2416
|
- Tables: Max 4 cols
|
|
1826
2417
|
- NO LaTeX${mode === "Flux" ? "" : ". Kaomojis"}
|
|
1827
|
-
|
|
1828
|
-
-- TURN RULES (PRIORITY: HIGH) --
|
|
1829
|
-
- End with [turn: continue] to continue or [turn: finish] to finish agent loop (MUST INCLUDE EVERY RESPONSE)
|
|
1830
|
-
- Tool Called? No post tool response until [turn: continue]
|
|
1831
|
-
- Task Complete? End loop with [turn: finish]
|
|
1832
|
-
- NEVER USE [turn: continue] [turn:finish] together
|
|
1833
2418
|
[/SYSTEM]`.trim();
|
|
1834
2419
|
};
|
|
1835
2420
|
getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
|
|
@@ -2667,134 +3252,17 @@ var init_usage = __esm({
|
|
|
2667
3252
|
"High": 0.045,
|
|
2668
3253
|
"Ultra": 0.0488,
|
|
2669
3254
|
"Premium": 0.1
|
|
2670
|
-
};
|
|
2671
|
-
const cost = costs[imageSettings.quality] || 2e-3;
|
|
2672
|
-
const stats = await getDailyUsage();
|
|
2673
|
-
if (!stats.imageCalls) {
|
|
2674
|
-
stats.imageCalls = [];
|
|
2675
|
-
}
|
|
2676
|
-
stats.imageCalls.push({
|
|
2677
|
-
timestamp: Date.now(),
|
|
2678
|
-
cost
|
|
2679
|
-
});
|
|
2680
|
-
queueFlush();
|
|
2681
|
-
};
|
|
2682
|
-
}
|
|
2683
|
-
});
|
|
2684
|
-
|
|
2685
|
-
// src/utils/arg_parser.js
|
|
2686
|
-
var parseArgs;
|
|
2687
|
-
var init_arg_parser = __esm({
|
|
2688
|
-
"src/utils/arg_parser.js"() {
|
|
2689
|
-
parseArgs = (argsString) => {
|
|
2690
|
-
const args = {};
|
|
2691
|
-
if (!argsString) return args;
|
|
2692
|
-
let i = 0;
|
|
2693
|
-
while (i < argsString.length) {
|
|
2694
|
-
while (i < argsString.length && /[\s,]/.test(argsString[i])) i++;
|
|
2695
|
-
if (i >= argsString.length) break;
|
|
2696
|
-
let keyMatch = argsString.substring(i).match(/^(\w+)\s*=\s*/);
|
|
2697
|
-
if (!keyMatch) {
|
|
2698
|
-
i++;
|
|
2699
|
-
continue;
|
|
2700
|
-
}
|
|
2701
|
-
const key = keyMatch[1];
|
|
2702
|
-
i += keyMatch[0].length;
|
|
2703
|
-
let value = "";
|
|
2704
|
-
if (i < argsString.length && (argsString[i] === '"' || argsString[i] === "'" || argsString[i] === "`")) {
|
|
2705
|
-
const quote = argsString[i];
|
|
2706
|
-
i++;
|
|
2707
|
-
let start = i;
|
|
2708
|
-
let end = -1;
|
|
2709
|
-
let searchIndex = i;
|
|
2710
|
-
while (searchIndex < argsString.length) {
|
|
2711
|
-
let qIdx = argsString.indexOf(quote, searchIndex);
|
|
2712
|
-
if (qIdx === -1) break;
|
|
2713
|
-
if (argsString[qIdx - 1] === "\\" && argsString[qIdx - 2] !== "\\") {
|
|
2714
|
-
searchIndex = qIdx + 1;
|
|
2715
|
-
continue;
|
|
2716
|
-
}
|
|
2717
|
-
const after = argsString.substring(qIdx + 1).trim();
|
|
2718
|
-
const isLogicalEnd = after === "" || // End of entire string
|
|
2719
|
-
after.startsWith(",") || // Next argument separator
|
|
2720
|
-
/^(\w+)\s*=/.test(after) || // Next argument key=
|
|
2721
|
-
after.startsWith(")") && (after.length === 1 || /^\)\s*([,\]\s]|tool:)/i.test(after));
|
|
2722
|
-
if (isLogicalEnd) {
|
|
2723
|
-
end = qIdx;
|
|
2724
|
-
break;
|
|
2725
|
-
}
|
|
2726
|
-
searchIndex = qIdx + 1;
|
|
2727
|
-
}
|
|
2728
|
-
if (end !== -1) {
|
|
2729
|
-
value = argsString.substring(start, end);
|
|
2730
|
-
i = end + 1;
|
|
2731
|
-
} else {
|
|
2732
|
-
value = argsString.substring(start);
|
|
2733
|
-
i = argsString.length;
|
|
2734
|
-
}
|
|
2735
|
-
const isPathKey = key.toLowerCase().includes("path") || ["dest", "source", "to", "from"].includes(key.toLowerCase());
|
|
2736
|
-
if (isPathKey) {
|
|
2737
|
-
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\`/g, "`").replace(/\\\\/g, "\\");
|
|
2738
|
-
} else {
|
|
2739
|
-
try {
|
|
2740
|
-
if (value.includes("\\")) {
|
|
2741
|
-
const surgicalValue = value.replace(/(^|[^\\])"/g, '$1\\"');
|
|
2742
|
-
value = JSON.parse(`"${surgicalValue.replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`);
|
|
2743
|
-
}
|
|
2744
|
-
} catch (e) {
|
|
2745
|
-
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'").replace(/\\`/g, "`").replace(/\\\\/g, "\\").replace(/\\n/g, "\n");
|
|
2746
|
-
}
|
|
2747
|
-
}
|
|
2748
|
-
} else if (i < argsString.length && argsString[i] === "[") {
|
|
2749
|
-
let balance = 0;
|
|
2750
|
-
let inString = null;
|
|
2751
|
-
let start = i;
|
|
2752
|
-
let end = -1;
|
|
2753
|
-
for (let j = i; j < argsString.length; j++) {
|
|
2754
|
-
const char = argsString[j];
|
|
2755
|
-
if (!inString && (char === '"' || char === "'" || char === "`")) {
|
|
2756
|
-
inString = char;
|
|
2757
|
-
} else if (inString && char === inString && argsString[j - 1] !== "\\") {
|
|
2758
|
-
inString = null;
|
|
2759
|
-
}
|
|
2760
|
-
if (!inString) {
|
|
2761
|
-
if (char === "[") balance++;
|
|
2762
|
-
else if (char === "]") balance--;
|
|
2763
|
-
if (balance === 0) {
|
|
2764
|
-
end = j;
|
|
2765
|
-
break;
|
|
2766
|
-
}
|
|
2767
|
-
}
|
|
2768
|
-
}
|
|
2769
|
-
if (end !== -1) {
|
|
2770
|
-
value = argsString.substring(start, end + 1);
|
|
2771
|
-
i = end + 1;
|
|
2772
|
-
try {
|
|
2773
|
-
let normalized = value.trim();
|
|
2774
|
-
if (normalized.startsWith("'") || normalized.includes("'")) {
|
|
2775
|
-
}
|
|
2776
|
-
} catch (e) {
|
|
2777
|
-
}
|
|
2778
|
-
} else {
|
|
2779
|
-
value = argsString.substring(start);
|
|
2780
|
-
i = argsString.length;
|
|
2781
|
-
}
|
|
2782
|
-
} else {
|
|
2783
|
-
let endMatch = argsString.substring(i).match(/([^,\s\)]+)/);
|
|
2784
|
-
if (endMatch) {
|
|
2785
|
-
value = endMatch[1];
|
|
2786
|
-
i += value.length;
|
|
2787
|
-
}
|
|
2788
|
-
}
|
|
2789
|
-
if (value === "true") value = true;
|
|
2790
|
-
else if (value === "false") value = false;
|
|
2791
|
-
else if (typeof value === "string" && !isNaN(value) && value.trim() !== "") value = Number(value);
|
|
2792
|
-
if (typeof value === "string" && (key.toLowerCase().includes("path") || ["dest", "source", "to", "from"].includes(key.toLowerCase()))) {
|
|
2793
|
-
value = value.replace(/\x0C/g, "\\f").replace(/\x0D/g, "\\r").replace(/\x0B/g, "\\v").replace(/\x08/g, "\\b");
|
|
2794
|
-
}
|
|
2795
|
-
args[key] = value;
|
|
3255
|
+
};
|
|
3256
|
+
const cost = costs[imageSettings.quality] || 2e-3;
|
|
3257
|
+
const stats = await getDailyUsage();
|
|
3258
|
+
if (!stats.imageCalls) {
|
|
3259
|
+
stats.imageCalls = [];
|
|
2796
3260
|
}
|
|
2797
|
-
|
|
3261
|
+
stats.imageCalls.push({
|
|
3262
|
+
timestamp: Date.now(),
|
|
3263
|
+
cost
|
|
3264
|
+
});
|
|
3265
|
+
queueFlush();
|
|
2798
3266
|
};
|
|
2799
3267
|
}
|
|
2800
3268
|
});
|
|
@@ -3324,433 +3792,109 @@ var init_update_file = __esm({
|
|
|
3324
3792
|
}
|
|
3325
3793
|
if (matches.length > 1) {
|
|
3326
3794
|
results.push({ success: false, error: `Block ${i + 1}: Found ${matches.length} matches (must be unique).` });
|
|
3327
|
-
continue;
|
|
3328
|
-
}
|
|
3329
|
-
const startPos = matches[0].index;
|
|
3330
|
-
const firstMatchContent = matches[0][0];
|
|
3331
|
-
const lineStart = currentFileContent.lastIndexOf("\n", startPos) + 1;
|
|
3332
|
-
const leadingContext = currentFileContent.substring(lineStart, startPos);
|
|
3333
|
-
const finalReplacement = adjustIndentation(content_to_add, firstMatchContent, leadingContext);
|
|
3334
|
-
const allOriginalLines = currentFileContent.split("\n");
|
|
3335
|
-
const patchStartLine = currentFileContent.substring(0, startPos).split("\n").length;
|
|
3336
|
-
const patchOldLines = firstMatchContent.split("\n");
|
|
3337
|
-
const contextBefore = [];
|
|
3338
|
-
for (let j = Math.max(0, patchStartLine - 4); j < patchStartLine - 1; j++) {
|
|
3339
|
-
contextBefore.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3340
|
-
}
|
|
3341
|
-
const contextAfter = [];
|
|
3342
|
-
const patchEndLineIdx = patchStartLine + patchOldLines.length - 1;
|
|
3343
|
-
for (let j = patchEndLineIdx; j < Math.min(allOriginalLines.length, patchEndLineIdx + 3); j++) {
|
|
3344
|
-
contextAfter.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3345
|
-
}
|
|
3346
|
-
results.push({
|
|
3347
|
-
success: true,
|
|
3348
|
-
startPos,
|
|
3349
|
-
oldContent: firstMatchContent,
|
|
3350
|
-
newContent: finalReplacement,
|
|
3351
|
-
originalStartLine: patchStartLine,
|
|
3352
|
-
contextBefore,
|
|
3353
|
-
contextAfter
|
|
3354
|
-
});
|
|
3355
|
-
currentFileContent = currentFileContent.substring(0, startPos) + finalReplacement + currentFileContent.substring(startPos + firstMatchContent.length);
|
|
3356
|
-
totalInstances++;
|
|
3357
|
-
}
|
|
3358
|
-
if (totalInstances === 0) {
|
|
3359
|
-
return `ERROR: Failed to apply any patches to [${targetPath}].
|
|
3360
|
-
${results.map((r) => r.error).join("\n")}`;
|
|
3361
|
-
}
|
|
3362
|
-
fs10.writeFileSync(absolutePath, currentFileContent, "utf8");
|
|
3363
|
-
let diffText = `SUCCESS: File [${targetPath}] updated. [${totalInstances}/${patchPairs.length}] blocks applied.
|
|
3364
|
-
|
|
3365
|
-
`;
|
|
3366
|
-
diffText += `[DIFF_START]
|
|
3367
|
-
`;
|
|
3368
|
-
const terminalWidth = process.stdout.columns || 100;
|
|
3369
|
-
const separatorLine = "\u2550".repeat(Math.max(20, terminalWidth - 12));
|
|
3370
|
-
const allLinesFinal = currentFileContent.split("\n");
|
|
3371
|
-
const successfulPatches = results.filter((r) => r.success);
|
|
3372
|
-
successfulPatches.forEach((res, idx) => {
|
|
3373
|
-
if (idx === 0) {
|
|
3374
|
-
res.contextBefore.forEach((ctx) => {
|
|
3375
|
-
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3376
|
-
`;
|
|
3377
|
-
});
|
|
3378
|
-
} else {
|
|
3379
|
-
const prev = successfulPatches[idx - 1];
|
|
3380
|
-
const prevLinesCount = prev.newContent.split("\n").length;
|
|
3381
|
-
const prevEndLine = prev.originalStartLine + prevLinesCount - 1;
|
|
3382
|
-
const gap = res.originalStartLine - prevEndLine - 1;
|
|
3383
|
-
if (gap >= 1 && gap < 12) {
|
|
3384
|
-
for (let j = prevEndLine; j < res.originalStartLine - 1; j++) {
|
|
3385
|
-
diffText += `[UI_CONTEXT] ${j + 1} |${allLinesFinal[j]}
|
|
3386
|
-
`;
|
|
3387
|
-
}
|
|
3388
|
-
} else if (gap >= 12) {
|
|
3389
|
-
prev.contextAfter.forEach((ctx) => {
|
|
3390
|
-
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3391
|
-
`;
|
|
3392
|
-
});
|
|
3393
|
-
diffText += `[UI_CONTEXT] ${separatorLine}
|
|
3394
|
-
`;
|
|
3395
|
-
res.contextBefore.forEach((ctx) => {
|
|
3396
|
-
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3397
|
-
`;
|
|
3398
|
-
});
|
|
3399
|
-
}
|
|
3400
|
-
}
|
|
3401
|
-
const oldLines = res.oldContent.split("\n");
|
|
3402
|
-
const newLines = res.newContent.split("\n");
|
|
3403
|
-
oldLines.forEach((line, i) => {
|
|
3404
|
-
diffText += `-${res.originalStartLine + i}|${line}
|
|
3405
|
-
`;
|
|
3406
|
-
});
|
|
3407
|
-
newLines.forEach((line, i) => {
|
|
3408
|
-
diffText += `+${res.originalStartLine + i}|${line}
|
|
3409
|
-
`;
|
|
3410
|
-
});
|
|
3411
|
-
if (idx === successfulPatches.length - 1) {
|
|
3412
|
-
res.contextAfter.forEach((ctx) => {
|
|
3413
|
-
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3414
|
-
`;
|
|
3415
|
-
});
|
|
3416
|
-
}
|
|
3417
|
-
});
|
|
3418
|
-
diffText += `[DIFF_END]`;
|
|
3419
|
-
const errors = results.filter((r) => !r.success);
|
|
3420
|
-
if (errors.length > 0) {
|
|
3421
|
-
diffText += `
|
|
3422
|
-
|
|
3423
|
-
\u26A0\uFE0F WARNING: Some blocks failed:
|
|
3424
|
-
${errors.map((e) => ` \u2022 ${e.error}`).join("\n")}`;
|
|
3425
|
-
}
|
|
3426
|
-
return diffText;
|
|
3427
|
-
} catch (err) {
|
|
3428
|
-
return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
|
|
3429
|
-
}
|
|
3430
|
-
};
|
|
3431
|
-
}
|
|
3432
|
-
});
|
|
3433
|
-
|
|
3434
|
-
// src/tools/exec_command.js
|
|
3435
|
-
import { spawn } from "child_process";
|
|
3436
|
-
var pty, activeChildProcess, isActiveCommandPty, writeToActiveCommand, terminateActiveCommand, adjustWindowsCommand, exec_command, runStandardSpawn;
|
|
3437
|
-
var init_exec_command = __esm({
|
|
3438
|
-
async "src/tools/exec_command.js"() {
|
|
3439
|
-
init_arg_parser();
|
|
3440
|
-
init_main_tools();
|
|
3441
|
-
pty = null;
|
|
3442
|
-
try {
|
|
3443
|
-
const ptyModule = await import("node-pty");
|
|
3444
|
-
pty = ptyModule.default || ptyModule;
|
|
3445
|
-
} catch (err) {
|
|
3446
|
-
}
|
|
3447
|
-
activeChildProcess = null;
|
|
3448
|
-
isActiveCommandPty = false;
|
|
3449
|
-
writeToActiveCommand = (data) => {
|
|
3450
|
-
try {
|
|
3451
|
-
if (activeChildProcess) {
|
|
3452
|
-
if (isActiveCommandPty && typeof activeChildProcess.write === "function") {
|
|
3453
|
-
activeChildProcess.write(data);
|
|
3454
|
-
} else if (activeChildProcess.stdin && activeChildProcess.stdin.writable) {
|
|
3455
|
-
activeChildProcess.stdin.write(data);
|
|
3456
|
-
}
|
|
3457
|
-
}
|
|
3458
|
-
} catch (err) {
|
|
3459
|
-
}
|
|
3460
|
-
};
|
|
3461
|
-
terminateActiveCommand = () => {
|
|
3462
|
-
if (activeChildProcess) {
|
|
3463
|
-
try {
|
|
3464
|
-
if (isActiveCommandPty && typeof activeChildProcess.destroy === "function") {
|
|
3465
|
-
activeChildProcess.destroy();
|
|
3466
|
-
} else if (typeof activeChildProcess.kill === "function") {
|
|
3467
|
-
activeChildProcess.kill("SIGKILL");
|
|
3468
|
-
}
|
|
3469
|
-
} catch (err) {
|
|
3470
|
-
}
|
|
3471
|
-
activeChildProcess = null;
|
|
3472
|
-
isActiveCommandPty = false;
|
|
3473
|
-
}
|
|
3474
|
-
};
|
|
3475
|
-
adjustWindowsCommand = (command, usePowerShell = false) => {
|
|
3476
|
-
if (process.platform !== "win32") return command;
|
|
3477
|
-
const tokens = [];
|
|
3478
|
-
let current = "";
|
|
3479
|
-
let inQuote = null;
|
|
3480
|
-
let isEscaped = false;
|
|
3481
|
-
for (let i = 0; i < command.length; i++) {
|
|
3482
|
-
const char = command[i];
|
|
3483
|
-
if (isEscaped) {
|
|
3484
|
-
current += char;
|
|
3485
|
-
isEscaped = false;
|
|
3486
|
-
continue;
|
|
3487
|
-
}
|
|
3488
|
-
if (char === "\\") {
|
|
3489
|
-
if (command[i + 1] === " ") {
|
|
3490
|
-
current += " ";
|
|
3491
|
-
i++;
|
|
3492
|
-
continue;
|
|
3493
|
-
}
|
|
3494
|
-
current += char;
|
|
3495
|
-
isEscaped = true;
|
|
3496
|
-
continue;
|
|
3497
|
-
}
|
|
3498
|
-
if (inQuote) {
|
|
3499
|
-
if (char === inQuote) {
|
|
3500
|
-
inQuote = null;
|
|
3501
|
-
}
|
|
3502
|
-
current += char;
|
|
3503
|
-
} else {
|
|
3504
|
-
if (char === '"' || char === "'") {
|
|
3505
|
-
inQuote = char;
|
|
3506
|
-
current += char;
|
|
3507
|
-
} else if (char === ";" && !current.includes("://")) {
|
|
3508
|
-
if (current.length > 0) {
|
|
3509
|
-
tokens.push(current);
|
|
3510
|
-
current = "";
|
|
3511
|
-
}
|
|
3512
|
-
tokens.push(usePowerShell ? ";" : "&");
|
|
3513
|
-
} else if (char === "|" && !current.includes("://")) {
|
|
3514
|
-
if (current.length > 0) {
|
|
3515
|
-
tokens.push(current);
|
|
3516
|
-
current = "";
|
|
3517
|
-
}
|
|
3518
|
-
tokens.push("|");
|
|
3519
|
-
} else if (/\s/.test(char)) {
|
|
3520
|
-
if (current.length > 0) {
|
|
3521
|
-
tokens.push(current);
|
|
3522
|
-
current = "";
|
|
3523
|
-
}
|
|
3524
|
-
} else {
|
|
3525
|
-
current += char;
|
|
3526
|
-
}
|
|
3527
|
-
}
|
|
3528
|
-
}
|
|
3529
|
-
if (current.length > 0) {
|
|
3530
|
-
tokens.push(current);
|
|
3531
|
-
}
|
|
3532
|
-
const looksLikePath = (str) => {
|
|
3533
|
-
if (!str.includes("/")) return false;
|
|
3534
|
-
if (/^(https?|file|ftp):\/\//i.test(str)) return false;
|
|
3535
|
-
if (str.startsWith("/") && (str.match(/\//g) || []).length === 1) {
|
|
3536
|
-
return false;
|
|
3537
|
-
}
|
|
3538
|
-
if (/\s\/|\/\s/.test(str)) return false;
|
|
3539
|
-
if (/[\(\)\{\}\;\<\>\=\'\"]/.test(str)) return false;
|
|
3540
|
-
return true;
|
|
3541
|
-
};
|
|
3542
|
-
let inMkdir = false;
|
|
3543
|
-
const translatedTokens = [];
|
|
3544
|
-
for (let i = 0; i < tokens.length; i++) {
|
|
3545
|
-
const token = tokens[i];
|
|
3546
|
-
if (token === "mkdir" && usePowerShell && isPsAvailable()) {
|
|
3547
|
-
inMkdir = true;
|
|
3548
|
-
}
|
|
3549
|
-
if (inMkdir) {
|
|
3550
|
-
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
3551
|
-
if (controlOperators.includes(token)) {
|
|
3552
|
-
inMkdir = false;
|
|
3553
|
-
} else if (token === "-p" || token === "--parents") {
|
|
3554
|
-
translatedTokens.push("-Force");
|
|
3555
|
-
continue;
|
|
3556
|
-
}
|
|
3557
|
-
}
|
|
3558
|
-
if (token === "|" && tokens[i + 1] === "tee") {
|
|
3559
|
-
if (tokens[i + 2] === "-a") {
|
|
3560
|
-
translatedTokens.push(">>");
|
|
3561
|
-
i += 2;
|
|
3562
|
-
} else {
|
|
3563
|
-
translatedTokens.push(">");
|
|
3564
|
-
i += 1;
|
|
3565
|
-
}
|
|
3566
|
-
continue;
|
|
3567
|
-
}
|
|
3568
|
-
if (token === "|" && tokens[i + 1] === "cat" && tokens[i + 2] === ">") {
|
|
3569
|
-
translatedTokens.push(">");
|
|
3570
|
-
i += 2;
|
|
3571
|
-
continue;
|
|
3572
|
-
}
|
|
3573
|
-
if (token === "|") {
|
|
3574
|
-
const nextToken = tokens[i + 1];
|
|
3575
|
-
if (nextToken) {
|
|
3576
|
-
const nextUnquoted = nextToken.replace(/^['"]|['"]$/g, "");
|
|
3577
|
-
const isWritableFile = /\.(txt|md|json|log|csv|html|css|py|js|xml|yaml|yml|pdf|docx|pptx|xlsx)$/i.test(nextUnquoted);
|
|
3578
|
-
if (looksLikePath(nextUnquoted) && isWritableFile) {
|
|
3579
|
-
translatedTokens.push(">");
|
|
3580
|
-
continue;
|
|
3581
|
-
}
|
|
3795
|
+
continue;
|
|
3582
3796
|
}
|
|
3797
|
+
const startPos = matches[0].index;
|
|
3798
|
+
const firstMatchContent = matches[0][0];
|
|
3799
|
+
const lineStart = currentFileContent.lastIndexOf("\n", startPos) + 1;
|
|
3800
|
+
const leadingContext = currentFileContent.substring(lineStart, startPos);
|
|
3801
|
+
const finalReplacement = adjustIndentation(content_to_add, firstMatchContent, leadingContext);
|
|
3802
|
+
const allOriginalLines = currentFileContent.split("\n");
|
|
3803
|
+
const patchStartLine = currentFileContent.substring(0, startPos).split("\n").length;
|
|
3804
|
+
const patchOldLines = firstMatchContent.split("\n");
|
|
3805
|
+
const contextBefore = [];
|
|
3806
|
+
for (let j = Math.max(0, patchStartLine - 4); j < patchStartLine - 1; j++) {
|
|
3807
|
+
contextBefore.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3808
|
+
}
|
|
3809
|
+
const contextAfter = [];
|
|
3810
|
+
const patchEndLineIdx = patchStartLine + patchOldLines.length - 1;
|
|
3811
|
+
for (let j = patchEndLineIdx; j < Math.min(allOriginalLines.length, patchEndLineIdx + 3); j++) {
|
|
3812
|
+
contextAfter.push({ num: j + 1, text: allOriginalLines[j] });
|
|
3813
|
+
}
|
|
3814
|
+
results.push({
|
|
3815
|
+
success: true,
|
|
3816
|
+
startPos,
|
|
3817
|
+
oldContent: firstMatchContent,
|
|
3818
|
+
newContent: finalReplacement,
|
|
3819
|
+
originalStartLine: patchStartLine,
|
|
3820
|
+
contextBefore,
|
|
3821
|
+
contextAfter
|
|
3822
|
+
});
|
|
3823
|
+
currentFileContent = currentFileContent.substring(0, startPos) + finalReplacement + currentFileContent.substring(startPos + firstMatchContent.length);
|
|
3824
|
+
totalInstances++;
|
|
3583
3825
|
}
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
const processedTokens = translatedTokens.map((token) => {
|
|
3588
|
-
if (token === "echo") {
|
|
3589
|
-
inEchoArguments = true;
|
|
3590
|
-
return token;
|
|
3591
|
-
}
|
|
3592
|
-
const controlOperators = [">", ">>", "<", "&", "&&", "|", "||", ";"];
|
|
3593
|
-
if (controlOperators.includes(token)) {
|
|
3594
|
-
inEchoArguments = false;
|
|
3595
|
-
}
|
|
3596
|
-
const hasOuterQuotes = /^['"]|['"]$/.test(token);
|
|
3597
|
-
let processed = token;
|
|
3598
|
-
if (inEchoArguments && hasOuterQuotes) {
|
|
3599
|
-
processed = token.replace(/^['"]|['"]$/g, "");
|
|
3600
|
-
}
|
|
3601
|
-
const currentHasOuterQuotes = /^['"]|['"]$/.test(processed);
|
|
3602
|
-
const unquoted = processed.replace(/^['"]|['"]$/g, "");
|
|
3603
|
-
if (looksLikePath(unquoted)) {
|
|
3604
|
-
processed = processed.replace(/\//g, "\\");
|
|
3605
|
-
}
|
|
3606
|
-
const finalUnquoted = processed.replace(/^['"]|['"]$/g, "");
|
|
3607
|
-
if (finalUnquoted.includes(" ") && !currentHasOuterQuotes) {
|
|
3608
|
-
processed = `"${finalUnquoted}"`;
|
|
3826
|
+
if (totalInstances === 0) {
|
|
3827
|
+
return `ERROR: Failed to apply any patches to [${targetPath}].
|
|
3828
|
+
${results.map((r) => r.error).join("\n")}`;
|
|
3609
3829
|
}
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
return processedTokens.join(" ");
|
|
3613
|
-
};
|
|
3614
|
-
exec_command = async (args, options = {}) => {
|
|
3615
|
-
const { command: rawCommand } = parseArgs(args);
|
|
3616
|
-
const { onChunk } = options;
|
|
3617
|
-
if (!rawCommand) return 'ERROR: Missing "command" argument for exec_command.';
|
|
3618
|
-
const isWin = process.platform === "win32";
|
|
3619
|
-
const systemSettings = options.systemSettings || {};
|
|
3620
|
-
const netEnv = {};
|
|
3621
|
-
if (systemSettings.networkAccess === false) {
|
|
3622
|
-
netEnv.HTTP_PROXY = "http://127.0.0.1:9999";
|
|
3623
|
-
netEnv.HTTPS_PROXY = "http://127.0.0.1:9999";
|
|
3624
|
-
netEnv.ALL_PROXY = "socks5://127.0.0.1:9999";
|
|
3625
|
-
netEnv.http_proxy = "http://127.0.0.1:9999";
|
|
3626
|
-
netEnv.https_proxy = "http://127.0.0.1:9999";
|
|
3627
|
-
netEnv.all_proxy = "socks5://127.0.0.1:9999";
|
|
3628
|
-
netEnv.NO_PROXY = "localhost,127.0.0.1";
|
|
3629
|
-
}
|
|
3630
|
-
return new Promise((resolve) => {
|
|
3631
|
-
const attempt = (usePowerShell) => {
|
|
3632
|
-
const command = adjustWindowsCommand(rawCommand, usePowerShell);
|
|
3633
|
-
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
3634
|
-
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
3635
|
-
if (pty) {
|
|
3636
|
-
try {
|
|
3637
|
-
const ptyProcess = pty.spawn(shell, shellArgs, {
|
|
3638
|
-
name: "xterm-256color",
|
|
3639
|
-
cols: options.cols || 120,
|
|
3640
|
-
rows: options.rows || 30,
|
|
3641
|
-
cwd: process.cwd(),
|
|
3642
|
-
env: {
|
|
3643
|
-
...process.env,
|
|
3644
|
-
CI: "false",
|
|
3645
|
-
TERM: "xterm-256color",
|
|
3646
|
-
FORCE_COLOR: "1",
|
|
3647
|
-
...netEnv
|
|
3648
|
-
}
|
|
3649
|
-
});
|
|
3650
|
-
activeChildProcess = ptyProcess;
|
|
3651
|
-
isActiveCommandPty = true;
|
|
3652
|
-
let output = "";
|
|
3653
|
-
ptyProcess.onData((data) => {
|
|
3654
|
-
output += data;
|
|
3655
|
-
if (onChunk) onChunk(data);
|
|
3656
|
-
});
|
|
3657
|
-
ptyProcess.onExit(({ exitCode }) => {
|
|
3658
|
-
activeChildProcess = null;
|
|
3659
|
-
const normalizedOutput = (output || "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3660
|
-
const finalOutput = normalizedOutput || "Command executed with no output.";
|
|
3661
|
-
if (exitCode !== 0) {
|
|
3662
|
-
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${exitCode}].
|
|
3663
|
-
|
|
3664
|
-
${finalOutput}`);
|
|
3665
|
-
} else {
|
|
3666
|
-
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
3830
|
+
fs10.writeFileSync(absolutePath, currentFileContent, "utf8");
|
|
3831
|
+
let diffText = `SUCCESS: File [${targetPath}] updated. [${totalInstances}/${patchPairs.length}] blocks applied.
|
|
3667
3832
|
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3833
|
+
`;
|
|
3834
|
+
diffText += `[DIFF_START]
|
|
3835
|
+
`;
|
|
3836
|
+
const terminalWidth = process.stdout.columns || 100;
|
|
3837
|
+
const separatorLine = "\u2550".repeat(Math.max(20, terminalWidth - 12));
|
|
3838
|
+
const allLinesFinal = currentFileContent.split("\n");
|
|
3839
|
+
const successfulPatches = results.filter((r) => r.success);
|
|
3840
|
+
successfulPatches.forEach((res, idx) => {
|
|
3841
|
+
if (idx === 0) {
|
|
3842
|
+
res.contextBefore.forEach((ctx) => {
|
|
3843
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3844
|
+
`;
|
|
3845
|
+
});
|
|
3846
|
+
} else {
|
|
3847
|
+
const prev = successfulPatches[idx - 1];
|
|
3848
|
+
const prevLinesCount = prev.newContent.split("\n").length;
|
|
3849
|
+
const prevEndLine = prev.originalStartLine + prevLinesCount - 1;
|
|
3850
|
+
const gap = res.originalStartLine - prevEndLine - 1;
|
|
3851
|
+
if (gap >= 1 && gap < 12) {
|
|
3852
|
+
for (let j = prevEndLine; j < res.originalStartLine - 1; j++) {
|
|
3853
|
+
diffText += `[UI_CONTEXT] ${j + 1} |${allLinesFinal[j]}
|
|
3854
|
+
`;
|
|
3675
3855
|
}
|
|
3676
|
-
|
|
3677
|
-
|
|
3856
|
+
} else if (gap >= 12) {
|
|
3857
|
+
prev.contextAfter.forEach((ctx) => {
|
|
3858
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3859
|
+
`;
|
|
3860
|
+
});
|
|
3861
|
+
diffText += `[UI_CONTEXT] ${separatorLine}
|
|
3862
|
+
`;
|
|
3863
|
+
res.contextBefore.forEach((ctx) => {
|
|
3864
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3865
|
+
`;
|
|
3866
|
+
});
|
|
3678
3867
|
}
|
|
3679
|
-
} else {
|
|
3680
|
-
runStandardSpawn(resolve, command, rawCommand, netEnv, onChunk, usePowerShell);
|
|
3681
|
-
return true;
|
|
3682
3868
|
}
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3869
|
+
const oldLines = res.oldContent.split("\n");
|
|
3870
|
+
const newLines = res.newContent.split("\n");
|
|
3871
|
+
oldLines.forEach((line, i) => {
|
|
3872
|
+
diffText += `-${res.originalStartLine + i}|${line}
|
|
3873
|
+
`;
|
|
3874
|
+
});
|
|
3875
|
+
newLines.forEach((line, i) => {
|
|
3876
|
+
diffText += `+${res.originalStartLine + i}|${line}
|
|
3877
|
+
`;
|
|
3878
|
+
});
|
|
3879
|
+
if (idx === successfulPatches.length - 1) {
|
|
3880
|
+
res.contextAfter.forEach((ctx) => {
|
|
3881
|
+
diffText += `[UI_CONTEXT] ${ctx.num} |${ctx.text}
|
|
3882
|
+
`;
|
|
3883
|
+
});
|
|
3687
3884
|
}
|
|
3688
|
-
} else {
|
|
3689
|
-
attempt(false);
|
|
3690
|
-
}
|
|
3691
|
-
});
|
|
3692
|
-
};
|
|
3693
|
-
runStandardSpawn = (resolve, command, rawCommand, netEnv, onChunk, usePowerShell = true) => {
|
|
3694
|
-
const isWin = process.platform === "win32";
|
|
3695
|
-
const shell = isWin ? usePowerShell ? "powershell.exe" : "cmd.exe" : process.env.SHELL || "bash";
|
|
3696
|
-
const shellArgs = isWin ? usePowerShell ? ["-NoProfile", "-Command", command] : ["/c", command] : ["-c", command];
|
|
3697
|
-
const child = isWin ? spawn(shell, shellArgs, { cwd: process.cwd(), env: { ...process.env, ...netEnv } }) : spawn(command, {
|
|
3698
|
-
shell: true,
|
|
3699
|
-
cwd: process.cwd(),
|
|
3700
|
-
env: {
|
|
3701
|
-
...process.env,
|
|
3702
|
-
CI: "false",
|
|
3703
|
-
TERM: "xterm-256color",
|
|
3704
|
-
FORCE_COLOR: "1",
|
|
3705
|
-
...netEnv
|
|
3706
|
-
}
|
|
3707
|
-
});
|
|
3708
|
-
activeChildProcess = child;
|
|
3709
|
-
isActiveCommandPty = false;
|
|
3710
|
-
if (child.stdin) {
|
|
3711
|
-
child.stdin.on("error", () => {
|
|
3712
|
-
activeChildProcess = null;
|
|
3713
3885
|
});
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
const chunk = data.toString();
|
|
3719
|
-
stdout += chunk;
|
|
3720
|
-
if (onChunk) onChunk(chunk);
|
|
3721
|
-
});
|
|
3722
|
-
child.stderr.on("data", (data) => {
|
|
3723
|
-
const chunk = data.toString();
|
|
3724
|
-
stderr += chunk;
|
|
3725
|
-
if (onChunk) onChunk(chunk);
|
|
3726
|
-
});
|
|
3727
|
-
child.on("close", (code) => {
|
|
3728
|
-
activeChildProcess = null;
|
|
3729
|
-
const result = [];
|
|
3730
|
-
if (stdout) result.push(`STDOUT:
|
|
3731
|
-
${stdout}`);
|
|
3732
|
-
if (stderr) result.push(`STDERR:
|
|
3733
|
-
${stderr}`);
|
|
3734
|
-
if (code !== 0) result.push(`EXIT CODE: ${code}`);
|
|
3735
|
-
const finalOutput = result.join("\n\n") || "Command executed with no output.";
|
|
3736
|
-
if (code !== 0) {
|
|
3737
|
-
resolve(`ERROR: Command [${rawCommand}] failed with exit code [${code}].
|
|
3738
|
-
|
|
3739
|
-
${finalOutput}`);
|
|
3740
|
-
} else {
|
|
3741
|
-
resolve(`SUCCESS: Command [${rawCommand}] completed.
|
|
3886
|
+
diffText += `[DIFF_END]`;
|
|
3887
|
+
const errors = results.filter((r) => !r.success);
|
|
3888
|
+
if (errors.length > 0) {
|
|
3889
|
+
diffText += `
|
|
3742
3890
|
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
});
|
|
3746
|
-
child.on("error", (err) => {
|
|
3747
|
-
if (isWin && usePowerShell && err.code === "ENOENT") {
|
|
3748
|
-
const cmdCommand = adjustWindowsCommand(rawCommand, false);
|
|
3749
|
-
return runStandardSpawn(resolve, cmdCommand, rawCommand, netEnv, onChunk, false);
|
|
3891
|
+
\u26A0\uFE0F WARNING: Some blocks failed:
|
|
3892
|
+
${errors.map((e) => ` \u2022 ${e.error}`).join("\n")}`;
|
|
3750
3893
|
}
|
|
3751
|
-
|
|
3752
|
-
|
|
3753
|
-
|
|
3894
|
+
return diffText;
|
|
3895
|
+
} catch (err) {
|
|
3896
|
+
return `ERROR: Failed to update file [${targetPath}]: ${err.message}`;
|
|
3897
|
+
}
|
|
3754
3898
|
};
|
|
3755
3899
|
}
|
|
3756
3900
|
});
|
|
@@ -4640,7 +4784,7 @@ var init_tools = __esm({
|
|
|
4640
4784
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
4641
4785
|
import path15 from "path";
|
|
4642
4786
|
import fs16 from "fs";
|
|
4643
|
-
var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, consolidatePastMemories, getAIStream;
|
|
4787
|
+
var client, TERMINATION_SIGNAL, stripAnsi2, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, consolidatePastMemories, getAIStream;
|
|
4644
4788
|
var init_ai = __esm({
|
|
4645
4789
|
async "src/utils/ai.js"() {
|
|
4646
4790
|
init_prompts();
|
|
@@ -4654,6 +4798,10 @@ var init_ai = __esm({
|
|
|
4654
4798
|
init_revert();
|
|
4655
4799
|
client = null;
|
|
4656
4800
|
TERMINATION_SIGNAL = false;
|
|
4801
|
+
stripAnsi2 = (str) => {
|
|
4802
|
+
if (typeof str !== "string") return str;
|
|
4803
|
+
return str.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, "");
|
|
4804
|
+
};
|
|
4657
4805
|
signalTermination = () => {
|
|
4658
4806
|
TERMINATION_SIGNAL = true;
|
|
4659
4807
|
};
|
|
@@ -4693,7 +4841,7 @@ var init_ai = __esm({
|
|
|
4693
4841
|
const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
|
|
4694
4842
|
const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
|
|
4695
4843
|
const janitorContents = history.slice(0, -1).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:") && !msg.isMeta && !msg.isLogo && !String(msg.id).startsWith("welcome") && !String(msg.id).startsWith("logo")).slice(-14).map((msg) => {
|
|
4696
|
-
let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[METADATA \(PRIORITY: DYNAMIC\)\] Time: ([^|\n]+)/g, (match, p1) => {
|
|
4844
|
+
let processedText = stripAnsi2(msg.text).replace(/\[tool:functions\..*?\]/g, "").replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[METADATA \(PRIORITY: DYNAMIC\)\] Time: ([^|\n]+)/g, (match, p1) => {
|
|
4697
4845
|
return `[METADATA (PRIORITY: DYNAMIC)] Time: ${p1.replace(/:\d{2}/g, "")}`;
|
|
4698
4846
|
}).replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
|
|
4699
4847
|
const limit = msg.role === "user" ? USER_CONTEXT_LENGTH : AGENT_CONTEXT_LENGTH;
|
|
@@ -6826,6 +6974,11 @@ function App({ args = [] }) {
|
|
|
6826
6974
|
isTruncated: startIdx > 0
|
|
6827
6975
|
};
|
|
6828
6976
|
}, [messages, terminalSize.columns, terminalSize.rows]);
|
|
6977
|
+
const isTerminalWaitingForInput = useMemo2(() => {
|
|
6978
|
+
if (!activeCommand || !execOutput) return false;
|
|
6979
|
+
const lastChunk = execOutput.trim();
|
|
6980
|
+
return lastChunk.endsWith("?") || lastChunk.endsWith(":") || /\[[yYnN/]+\]\s*$/.test(lastChunk);
|
|
6981
|
+
}, [activeCommand, execOutput]);
|
|
6829
6982
|
const terminalWidth = stdout?.columns || 80;
|
|
6830
6983
|
const wrapWidth = Math.max(20, terminalWidth - 10);
|
|
6831
6984
|
const wrappedLinesCount = input.split(/\r?\n/).reduce((acc, line) => {
|
|
@@ -6849,6 +7002,23 @@ function App({ args = [] }) {
|
|
|
6849
7002
|
writeToActiveCommand("\b \b");
|
|
6850
7003
|
setExecOutput((prev) => prev.slice(0, -1));
|
|
6851
7004
|
}
|
|
7005
|
+
} else if (key.upArrow) {
|
|
7006
|
+
writeToActiveCommand(key.shift ? "\x1B[1;2A" : "\x1B[A");
|
|
7007
|
+
} else if (key.downArrow) {
|
|
7008
|
+
writeToActiveCommand(key.shift ? "\x1B[1;2B" : "\x1B[B");
|
|
7009
|
+
} else if (key.rightArrow) {
|
|
7010
|
+
writeToActiveCommand(key.shift ? "\x1B[1;2C" : "\x1B[C");
|
|
7011
|
+
} else if (key.leftArrow) {
|
|
7012
|
+
writeToActiveCommand(key.shift ? "\x1B[1;2D" : "\x1B[D");
|
|
7013
|
+
} else if (key.escape) {
|
|
7014
|
+
writeToActiveCommand("\x1B");
|
|
7015
|
+
} else if (key.ctrl && inputText) {
|
|
7016
|
+
const charCode = inputText.toLowerCase().charCodeAt(0);
|
|
7017
|
+
if (charCode >= 97 && charCode <= 122) {
|
|
7018
|
+
writeToActiveCommand(String.fromCharCode(charCode - 96));
|
|
7019
|
+
} else {
|
|
7020
|
+
writeToActiveCommand(inputText);
|
|
7021
|
+
}
|
|
6852
7022
|
} else if (inputText) {
|
|
6853
7023
|
writeToActiveCommand(inputText);
|
|
6854
7024
|
if (!isActiveCommandPty) setExecOutput((prev) => prev + inputText);
|
|
@@ -8745,7 +8915,7 @@ Selection: ${val}`,
|
|
|
8745
8915
|
newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
|
|
8746
8916
|
}
|
|
8747
8917
|
}
|
|
8748
|
-
)))) : /* @__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(
|
|
8918
|
+
)))) : /* @__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" }, isTerminalWaitingForInput ? " Terminal is waiting for USER input, Press TAB to interact" : " 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(
|
|
8749
8919
|
MultilineInput,
|
|
8750
8920
|
{
|
|
8751
8921
|
key: `input-${inputKey}`,
|
|
@@ -8857,7 +9027,7 @@ var init_app = __esm({
|
|
|
8857
9027
|
init_ChatLayout();
|
|
8858
9028
|
init_StatusBar();
|
|
8859
9029
|
init_CommandMenu();
|
|
8860
|
-
init_SettingsMenu();
|
|
9030
|
+
await init_SettingsMenu();
|
|
8861
9031
|
init_ProfileForm();
|
|
8862
9032
|
init_AskUserModal();
|
|
8863
9033
|
init_secrets();
|