fluxflow-cli 1.9.30 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/TOOLS.md +9 -3
- package/dist/fluxflow.js +708 -295
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -155,6 +155,7 @@ var init_ChatLayout = __esm({
|
|
|
155
155
|
"search_keyword": "FindFiles",
|
|
156
156
|
"write_pdf": "CreatePDF",
|
|
157
157
|
"write_docx": "CreateDocument",
|
|
158
|
+
"generate_image": "GenerateImage",
|
|
158
159
|
// PascalCase Support
|
|
159
160
|
"WriteFile": "WriteFile",
|
|
160
161
|
"PatchFile": "PatchFile",
|
|
@@ -167,7 +168,8 @@ var init_ChatLayout = __esm({
|
|
|
167
168
|
"WritePDF": "WritePDF",
|
|
168
169
|
"WriteDoc": "WriteDoc",
|
|
169
170
|
"Memory": "Memory",
|
|
170
|
-
"Chat": "Chat"
|
|
171
|
+
"Chat": "Chat",
|
|
172
|
+
"GenerateImage": "GenerateImage"
|
|
171
173
|
};
|
|
172
174
|
cleanSignals = (text) => {
|
|
173
175
|
if (!text) return text;
|
|
@@ -223,7 +225,7 @@ var init_ChatLayout = __esm({
|
|
|
223
225
|
}
|
|
224
226
|
}
|
|
225
227
|
}
|
|
226
|
-
return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
|
|
228
|
+
return result.replace(/^\[TOOL_RESULT\]:\s*/gi, "").split("\n").filter((line) => !line.trim().startsWith("SUCCESS:") && !line.trim().startsWith("ERROR:")).join("\n").replace(/\[\s*turn\s*:\s*(continue|finish)\s*\]/gi, "").replace(/\[\s*turn\s*:?.*?$/gi, "").replace(/\n\s*turn\s*:?.*?$/gi, "").replace(/\[\s*$/gi, "").replace(/\n\nResponded on .*/g, "").replace(/\n\n\[Prompted on: .*\]/g, "").replace(/(\$?\\?\/?\\rightarrow\$?|\$\\rightarrow\$)/gi, "\u2192").replace(/(\$?\\?\/?\\leftarrow\$?|\$\\leftarrow\$)/gi, "\u2190").replace(/(\$?\\?\/?\\uparrow\$?|\$\\uparrow\$)/gi, "\u2191").replace(/(\$?\\?\/?\\downarrow\$?|\$\\downarrow\$)/gi, "\u2193").replace(/(\$?\\?\/?\\leftrightarrow\$?|\$\\leftrightarrow\$)/gi, "\u2194").replace(/@\[TerminalName:.*?, ProcessId:.*?\]/gi, "").replace(/\b(write_file|update_file|read_folder|view_file|exec_command|web_search|web_scrape|search_keyword|write_pdf|write_docx|generate_image)\b/gi, (match) => TOOL_LABELS[match.toLowerCase()] || match).trim();
|
|
227
229
|
};
|
|
228
230
|
formatThinkText = (cleaned, columns = 80) => {
|
|
229
231
|
if (!cleaned) return null;
|
|
@@ -440,6 +442,9 @@ var init_ChatLayout = __esm({
|
|
|
440
442
|
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1 }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 1, paddingY: 0 }, /* @__PURE__ */ React2.createElement(Text2, { color: "red", bold: true, underline: true }, "\u274C PATCH FAILED"), /* @__PURE__ */ React2.createElement(Box2, { marginTop: 1 }, /* @__PURE__ */ React2.createElement(Text2, { color: "red" }, "Patch failed: ", /* @__PURE__ */ React2.createElement(Text2, { color: "white", bold: true }, "Model generated malformed edit.")))));
|
|
441
443
|
}
|
|
442
444
|
if (msg.role === "system" && msg.text?.includes("[TOOL RESULT]") && !isDiffResult && !isTerminalRecord && !isPatchError) return null;
|
|
445
|
+
if (msg.isImageStats) {
|
|
446
|
+
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 0, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, backgroundColor: "#0e1b21" }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, "\u{1F4B3} IMAGE STATS")), /* @__PURE__ */ React2.createElement(Box2, { paddingX: 1, marginTop: 1, marginBottom: 1, flexDirection: "column" }, msg.text.split("\n").map((line, i) => /* @__PURE__ */ React2.createElement(Text2, { key: i, color: "white" }, line)))));
|
|
447
|
+
}
|
|
443
448
|
if (msg.isAskRecord) {
|
|
444
449
|
const selectionMatch = msg.text.match(/Selection: (.*)/);
|
|
445
450
|
const selection = selectionMatch ? selectionMatch[1] : "No selection";
|
|
@@ -460,36 +465,10 @@ var init_ChatLayout = __esm({
|
|
|
460
465
|
{ cmd: "/resume", desc: "Load previous session" },
|
|
461
466
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
462
467
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
463
|
-
{
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
{ cmd: "flux", desc: "Enable Dev toolset" },
|
|
468
|
-
{ cmd: "flow", desc: "Enable Chat mode" }
|
|
469
|
-
]
|
|
470
|
-
},
|
|
471
|
-
{
|
|
472
|
-
cmd: "/thinking",
|
|
473
|
-
desc: "Set AI reasoning depth",
|
|
474
|
-
subs: [
|
|
475
|
-
{ cmd: "low", desc: "Fastest reasoning" },
|
|
476
|
-
{ cmd: "medium", desc: "Balanced depth" },
|
|
477
|
-
{ cmd: "high", desc: "Complex coding" },
|
|
478
|
-
{ cmd: "max", desc: "Architectural depth" },
|
|
479
|
-
{ cmd: "show", desc: "Show full thoughts" },
|
|
480
|
-
{ cmd: "hide", desc: "Show concise thoughts" }
|
|
481
|
-
]
|
|
482
|
-
},
|
|
483
|
-
{
|
|
484
|
-
cmd: "/model",
|
|
485
|
-
desc: "Switch AI model",
|
|
486
|
-
subs: [
|
|
487
|
-
{ cmd: "gemma-4-31b-it", desc: "Standard Default (Free, Recommended)" },
|
|
488
|
-
{ cmd: "gemini-3.1-pro-preview", desc: "Most Capable (Paid)" },
|
|
489
|
-
{ cmd: "gemini-3-flash-preview", desc: "Fast & Lightweight (Paid, Free limited quota)" },
|
|
490
|
-
{ cmd: "gemini-3.1-flash-lite", desc: "Ultra Fast (Paid, Free limited quota)" }
|
|
491
|
-
]
|
|
492
|
-
},
|
|
468
|
+
{ cmd: "/image", desc: "Generate images" },
|
|
469
|
+
{ cmd: "/mode", desc: "Toggle Flux/Flow modes" },
|
|
470
|
+
{ cmd: "/thinking", desc: "Set AI reasoning depth" },
|
|
471
|
+
{ cmd: "/model", desc: "Switch AI model" },
|
|
493
472
|
{ cmd: "/settings", desc: "Configure system prefs" },
|
|
494
473
|
{ cmd: "/key", desc: "Manage API keys" },
|
|
495
474
|
{ cmd: "/profile", desc: "Edit developer persona" },
|
|
@@ -498,21 +477,8 @@ var init_ChatLayout = __esm({
|
|
|
498
477
|
{ cmd: "/reset", desc: "Wipe all project data" },
|
|
499
478
|
{ cmd: "/about", desc: "Project info & credits" },
|
|
500
479
|
{ cmd: "/changelog", desc: "View latest updates" },
|
|
501
|
-
{
|
|
502
|
-
|
|
503
|
-
desc: "Project management",
|
|
504
|
-
subs: [
|
|
505
|
-
{ cmd: "init", desc: "Create FluxFlow.md template" }
|
|
506
|
-
]
|
|
507
|
-
},
|
|
508
|
-
{
|
|
509
|
-
cmd: "/update",
|
|
510
|
-
desc: "Check/Install updates",
|
|
511
|
-
subs: [
|
|
512
|
-
{ cmd: "check", desc: "Check for new version" },
|
|
513
|
-
{ cmd: "latest", desc: "Install latest release" }
|
|
514
|
-
]
|
|
515
|
-
}
|
|
480
|
+
{ cmd: "/fluxflow", desc: "Project management" },
|
|
481
|
+
{ cmd: "/update", desc: "Check/Install updates" }
|
|
516
482
|
];
|
|
517
483
|
return /* @__PURE__ */ React2.createElement(Box2, { marginBottom: 1, paddingX: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React2.createElement(Text2, { color: "magenta", bold: true, underline: true }, "\u{1F4DC} COMMAND REFERENCE"), /* @__PURE__ */ React2.createElement(Box2, { flexDirection: "column", marginTop: 1 }, commandList.map((c, i) => /* @__PURE__ */ React2.createElement(Box2, { key: i, flexDirection: "row" }, /* @__PURE__ */ React2.createElement(Box2, { width: 15 }, /* @__PURE__ */ React2.createElement(Text2, { color: "cyan", bold: true }, c.cmd)), /* @__PURE__ */ React2.createElement(Text2, { color: "gray" }, " - ", c.desc))))));
|
|
518
484
|
}
|
|
@@ -894,7 +860,7 @@ Suggest best options; don't ask for preferences. System handles the rest
|
|
|
894
860
|
1. Web Search: [tool:functions.WebSearch(query="...", limit=number)]. Find info (limit 3-10). Proactive use for unknown topics${mode === "Flux" ? " or docs" : ""}
|
|
895
861
|
2. Web Scrape: [tool:functions.WebScrape(url="...")]. Visit URL
|
|
896
862
|
|
|
897
|
-
${mode === "Flux" ? `-
|
|
863
|
+
${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
|
|
898
864
|
1. [tool:functions.ReadFile(path="...", start_line=N, end_line=N)]. Reads contents. Supports images/docs. User gives image/doc: VIEW FIRST
|
|
899
865
|
2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
|
|
900
866
|
3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? -> update_file > write_file
|
|
@@ -903,6 +869,7 @@ ${mode === "Flux" ? `- DEV TOOLS (path = relative to CWD) -
|
|
|
903
869
|
6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
|
|
904
870
|
7. [tool:functions.Run(command="...")]. Runs a shell command. Destructive/Irreversible ops -> ask user
|
|
905
871
|
8. [tool:functions.SearchKeyword(keyword="...")]. Global search. Finds definitions/logic without reading every file
|
|
872
|
+
9. Generate Image: [tool:functions.GenerateImage(title="...", prompt="...", path="... png", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. Generates image using AI. Usage: Mockups, PDF thumbnails, any visual content
|
|
906
873
|
|
|
907
874
|
- VERIFY RESULT CONTENTS. Fix errors. No hallucinations
|
|
908
875
|
- File tools > code chat
|
|
@@ -924,15 +891,12 @@ var init_janitor_tools = __esm({
|
|
|
924
891
|
"src/data/janitor_tools.js"() {
|
|
925
892
|
JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = true) => `
|
|
926
893
|
Your tool syntax is: '[tool:functions.ToolName(args...)]'
|
|
927
|
-
${needTitle ? `-- CHAT MANAGEMENT TOOLS --
|
|
928
|
-
1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY, MUST CALL THIS TOOL):
|
|
929
|
-
[tool:functions.Chat(title='<short creative title of FULL conversation in 3-5 words>')]. Consider full chat context to generate title NOT just latest message.`.trimEnd() : ""}
|
|
930
894
|
|
|
931
|
-
|
|
932
|
-
|
|
895
|
+
-- CHAT MANAGEMENT TOOLS (MUST CALL THESE 2 TOOLS ALWAYS) --
|
|
896
|
+
[tool:functions.Chat(title='<short creative title of FULL conversation in 3-5 words>')]. Consider full chat context to generate title NOT just latest message.
|
|
933
897
|
[tool:functions.Memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')]
|
|
934
898
|
|
|
935
|
-
${isMemoryEnabled ?
|
|
899
|
+
${isMemoryEnabled ? `-- User-specific long-term memory (USE BASED ON CONVERSATION CONTEXT) --
|
|
936
900
|
- Add: [tool:functions.Memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')]
|
|
937
901
|
- Delete: [tool:functions.Memory(action='user', method='delete', content='exact memory id')]
|
|
938
902
|
- Update: [tool:functions.Memory(action='user', method='update', content-new='string to update', content-old='exact memory id')]
|
|
@@ -1200,7 +1164,7 @@ var init_history = __esm({
|
|
|
1200
1164
|
// src/utils/usage.js
|
|
1201
1165
|
import fs6 from "fs-extra";
|
|
1202
1166
|
import path5 from "path";
|
|
1203
|
-
var cachedUsage, writeTimeout, lastWriteTime, isDirty, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota;
|
|
1167
|
+
var cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
1204
1168
|
var init_usage = __esm({
|
|
1205
1169
|
"src/utils/usage.js"() {
|
|
1206
1170
|
init_paths();
|
|
@@ -1208,31 +1172,36 @@ var init_usage = __esm({
|
|
|
1208
1172
|
writeTimeout = null;
|
|
1209
1173
|
lastWriteTime = 0;
|
|
1210
1174
|
isDirty = false;
|
|
1175
|
+
defaultStats = {
|
|
1176
|
+
agent: 0,
|
|
1177
|
+
background: 0,
|
|
1178
|
+
search: 0,
|
|
1179
|
+
toolSuccess: 0,
|
|
1180
|
+
toolFailure: 0,
|
|
1181
|
+
toolDenied: 0,
|
|
1182
|
+
duration: 0,
|
|
1183
|
+
tokens: 0,
|
|
1184
|
+
imageCalls: []
|
|
1185
|
+
};
|
|
1211
1186
|
loadUsageFromFile = async () => {
|
|
1212
1187
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1213
1188
|
try {
|
|
1214
1189
|
if (await fs6.exists(USAGE_FILE)) {
|
|
1215
1190
|
const data = await fs6.readJson(USAGE_FILE);
|
|
1216
1191
|
if (data && data.date === today && data.stats) {
|
|
1192
|
+
const mergedStats = { ...defaultStats, ...data.stats };
|
|
1193
|
+
if (!Array.isArray(mergedStats.imageCalls)) {
|
|
1194
|
+
mergedStats.imageCalls = [];
|
|
1195
|
+
}
|
|
1217
1196
|
return {
|
|
1218
1197
|
...data,
|
|
1219
|
-
stats:
|
|
1198
|
+
stats: mergedStats
|
|
1220
1199
|
};
|
|
1221
1200
|
}
|
|
1222
1201
|
}
|
|
1223
1202
|
} catch (err) {
|
|
1224
1203
|
}
|
|
1225
|
-
|
|
1226
|
-
agent: 0,
|
|
1227
|
-
background: 0,
|
|
1228
|
-
search: 0,
|
|
1229
|
-
toolSuccess: 0,
|
|
1230
|
-
toolFailure: 0,
|
|
1231
|
-
toolDenied: 0,
|
|
1232
|
-
duration: 0,
|
|
1233
|
-
tokens: 0
|
|
1234
|
-
};
|
|
1235
|
-
return { date: today, stats: defaultStats };
|
|
1204
|
+
return { date: today, stats: { ...defaultStats } };
|
|
1236
1205
|
};
|
|
1237
1206
|
flushUsage = async () => {
|
|
1238
1207
|
if (!isDirty || !cachedUsage) return;
|
|
@@ -1248,7 +1217,19 @@ var init_usage = __esm({
|
|
|
1248
1217
|
if (diskData && diskData.date === cachedUsage.date && diskData.stats) {
|
|
1249
1218
|
for (const key in cachedUsage.stats) {
|
|
1250
1219
|
if (diskData.stats[key] !== void 0) {
|
|
1251
|
-
|
|
1220
|
+
if (Array.isArray(cachedUsage.stats[key])) {
|
|
1221
|
+
const diskArr = Array.isArray(diskData.stats[key]) ? diskData.stats[key] : [];
|
|
1222
|
+
const memArr = cachedUsage.stats[key];
|
|
1223
|
+
const uniqueMap = /* @__PURE__ */ new Map();
|
|
1224
|
+
for (const item of [...diskArr, ...memArr]) {
|
|
1225
|
+
if (item && item.timestamp) {
|
|
1226
|
+
uniqueMap.set(item.timestamp, item);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
cachedUsage.stats[key] = Array.from(uniqueMap.values());
|
|
1230
|
+
} else if (typeof cachedUsage.stats[key] === "number") {
|
|
1231
|
+
cachedUsage.stats[key] = Math.max(cachedUsage.stats[key], Number(diskData.stats[key]) || 0);
|
|
1232
|
+
}
|
|
1252
1233
|
}
|
|
1253
1234
|
}
|
|
1254
1235
|
}
|
|
@@ -1291,20 +1272,14 @@ var init_usage = __esm({
|
|
|
1291
1272
|
} else if (cachedUsage.date !== today) {
|
|
1292
1273
|
cachedUsage = {
|
|
1293
1274
|
date: today,
|
|
1294
|
-
stats: {
|
|
1295
|
-
agent: 0,
|
|
1296
|
-
background: 0,
|
|
1297
|
-
search: 0,
|
|
1298
|
-
toolSuccess: 0,
|
|
1299
|
-
toolFailure: 0,
|
|
1300
|
-
toolDenied: 0,
|
|
1301
|
-
duration: 0,
|
|
1302
|
-
tokens: 0
|
|
1303
|
-
}
|
|
1275
|
+
stats: { ...defaultStats }
|
|
1304
1276
|
};
|
|
1305
1277
|
isDirty = true;
|
|
1306
1278
|
await flushUsage();
|
|
1307
1279
|
}
|
|
1280
|
+
if (cachedUsage && cachedUsage.stats && !Array.isArray(cachedUsage.stats.imageCalls)) {
|
|
1281
|
+
cachedUsage.stats.imageCalls = [];
|
|
1282
|
+
}
|
|
1308
1283
|
return cachedUsage.stats;
|
|
1309
1284
|
};
|
|
1310
1285
|
incrementUsage = async (key) => {
|
|
@@ -1338,6 +1313,67 @@ var init_usage = __esm({
|
|
|
1338
1313
|
}
|
|
1339
1314
|
return true;
|
|
1340
1315
|
};
|
|
1316
|
+
checkImageQuota = async (settings) => {
|
|
1317
|
+
const imageSettings = settings.imageSettings || { keyType: "Default", quality: "Low-High" };
|
|
1318
|
+
if (imageSettings.keyType !== "Default") return true;
|
|
1319
|
+
const costs = {
|
|
1320
|
+
"Low": 1e-3,
|
|
1321
|
+
"Low-High": 2e-3,
|
|
1322
|
+
"Medium": 8e-3,
|
|
1323
|
+
"Medium-High": 0.01,
|
|
1324
|
+
"High": 0.045,
|
|
1325
|
+
"Ultra": 0.0488,
|
|
1326
|
+
"Premium": 0.15
|
|
1327
|
+
};
|
|
1328
|
+
const currentCost = costs[imageSettings.quality] || 2e-3;
|
|
1329
|
+
const stats = await getDailyUsage();
|
|
1330
|
+
if (!stats.imageCalls) {
|
|
1331
|
+
stats.imageCalls = [];
|
|
1332
|
+
}
|
|
1333
|
+
const now = Date.now();
|
|
1334
|
+
const oneHourAgo = now - 60 * 60 * 1e3;
|
|
1335
|
+
const activeCalls = stats.imageCalls.filter((c) => c.timestamp >= oneHourAgo);
|
|
1336
|
+
const totalSpent = activeCalls.reduce((sum, c) => sum + c.cost, 0);
|
|
1337
|
+
return totalSpent + currentCost <= 0.02;
|
|
1338
|
+
};
|
|
1339
|
+
getImageQuotaStats = async () => {
|
|
1340
|
+
const stats = await getDailyUsage();
|
|
1341
|
+
if (!stats.imageCalls) {
|
|
1342
|
+
stats.imageCalls = [];
|
|
1343
|
+
}
|
|
1344
|
+
const now = Date.now();
|
|
1345
|
+
const oneHourAgo = now - 60 * 60 * 1e3;
|
|
1346
|
+
const activeCalls = stats.imageCalls.filter((c) => c.timestamp >= oneHourAgo);
|
|
1347
|
+
const totalSpent = activeCalls.reduce((sum, c) => sum + c.cost, 0);
|
|
1348
|
+
const remaining = Math.max(0, 0.02 - totalSpent);
|
|
1349
|
+
return {
|
|
1350
|
+
totalSpent,
|
|
1351
|
+
remaining,
|
|
1352
|
+
activeCallsCount: activeCalls.length
|
|
1353
|
+
};
|
|
1354
|
+
};
|
|
1355
|
+
recordImageGeneration = async (settings) => {
|
|
1356
|
+
const imageSettings = settings.imageSettings || { keyType: "Default", quality: "Low-High" };
|
|
1357
|
+
const costs = {
|
|
1358
|
+
"Low": 1e-3,
|
|
1359
|
+
"Low-High": 2e-3,
|
|
1360
|
+
"Medium": 8e-3,
|
|
1361
|
+
"Medium-High": 0.01,
|
|
1362
|
+
"High": 0.045,
|
|
1363
|
+
"Ultra": 0.0488,
|
|
1364
|
+
"Premium": 0.1
|
|
1365
|
+
};
|
|
1366
|
+
const cost = costs[imageSettings.quality] || 2e-3;
|
|
1367
|
+
const stats = await getDailyUsage();
|
|
1368
|
+
if (!stats.imageCalls) {
|
|
1369
|
+
stats.imageCalls = [];
|
|
1370
|
+
}
|
|
1371
|
+
stats.imageCalls.push({
|
|
1372
|
+
timestamp: Date.now(),
|
|
1373
|
+
cost
|
|
1374
|
+
});
|
|
1375
|
+
queueFlush();
|
|
1376
|
+
};
|
|
1341
1377
|
}
|
|
1342
1378
|
});
|
|
1343
1379
|
|
|
@@ -1460,8 +1496,6 @@ var init_arg_parser = __esm({
|
|
|
1460
1496
|
|
|
1461
1497
|
// src/tools/web_search.js
|
|
1462
1498
|
import puppeteer from "puppeteer";
|
|
1463
|
-
import fs7 from "fs";
|
|
1464
|
-
import path6 from "path";
|
|
1465
1499
|
var web_search;
|
|
1466
1500
|
var init_web_search = __esm({
|
|
1467
1501
|
"src/tools/web_search.js"() {
|
|
@@ -1485,7 +1519,7 @@ var init_web_search = __esm({
|
|
|
1485
1519
|
]
|
|
1486
1520
|
});
|
|
1487
1521
|
const page = await browser.newPage();
|
|
1488
|
-
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.
|
|
1522
|
+
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.7778.97 Safari/537.36");
|
|
1489
1523
|
await page.setViewport({ width: 1366, height: 768 });
|
|
1490
1524
|
const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
|
|
1491
1525
|
await new Promise((r) => setTimeout(r, jitter));
|
|
@@ -1515,16 +1549,6 @@ Snippet: ${snippet}`;
|
|
|
1515
1549
|
return `No results found for query: [${query}].`;
|
|
1516
1550
|
}
|
|
1517
1551
|
const finalResults = results.join("\n\n");
|
|
1518
|
-
const toolLogDir = path6.join(LOGS_DIR, "tools");
|
|
1519
|
-
if (!fs7.existsSync(toolLogDir)) fs7.mkdirSync(toolLogDir, { recursive: true });
|
|
1520
|
-
fs7.appendFileSync(path6.join(toolLogDir, "search-results.log"), `SEARCH ${(/* @__PURE__ */ new Date()).toLocaleString()} - Query: [${query}]. Count: ${results.length}.
|
|
1521
|
-
Content:
|
|
1522
|
-
${finalResults}
|
|
1523
|
-
|
|
1524
|
-
--------------------------------------------------------
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
`);
|
|
1528
1552
|
await browser.close();
|
|
1529
1553
|
return `Search results for [${query}]:
|
|
1530
1554
|
|
|
@@ -1545,8 +1569,6 @@ ${finalResults}`;
|
|
|
1545
1569
|
|
|
1546
1570
|
// src/tools/web_scrape.js
|
|
1547
1571
|
import puppeteer2 from "puppeteer";
|
|
1548
|
-
import fs8 from "fs";
|
|
1549
|
-
import path7 from "path";
|
|
1550
1572
|
var web_scrape;
|
|
1551
1573
|
var init_web_scrape = __esm({
|
|
1552
1574
|
"src/tools/web_scrape.js"() {
|
|
@@ -1569,7 +1591,7 @@ var init_web_scrape = __esm({
|
|
|
1569
1591
|
]
|
|
1570
1592
|
});
|
|
1571
1593
|
const page = await browser.newPage();
|
|
1572
|
-
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.
|
|
1594
|
+
await page.setUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.7778.97 Safari/537.36");
|
|
1573
1595
|
await page.setViewport({ width: 1366, height: 768 });
|
|
1574
1596
|
const jitter = attempt === 1 ? Math.random() * 1e3 + 500 : Math.random() * 2e3 + 1e3;
|
|
1575
1597
|
await new Promise((r) => setTimeout(r, jitter));
|
|
@@ -1613,16 +1635,6 @@ var init_web_scrape = __esm({
|
|
|
1613
1635
|
});
|
|
1614
1636
|
if (!htmlContent) throw new Error("EMPTY_RENDER_RESULT");
|
|
1615
1637
|
const cleanedHtml = htmlContent.replace(/\s+/g, " ").replace(/>\s+</g, "><").trim().substring(0, 3e4);
|
|
1616
|
-
const toolLogDir = path7.join(LOGS_DIR, "tools");
|
|
1617
|
-
if (!fs8.existsSync(toolLogDir)) fs8.mkdirSync(toolLogDir, { recursive: true });
|
|
1618
|
-
fs8.appendFileSync(path7.join(toolLogDir, "search-scraped.log"), `PUPPETEER ${(/* @__PURE__ */ new Date()).toLocaleString()} - URL: [${url}]. Length: ${cleanedHtml.length}.
|
|
1619
|
-
Content:
|
|
1620
|
-
${cleanedHtml}${htmlContent.length > 3e4 ? "\n\n[TRUNCATED AT 30K CHARS]" : ""}
|
|
1621
|
-
|
|
1622
|
-
--------------------------------------------------------
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
`);
|
|
1626
1638
|
await browser.close();
|
|
1627
1639
|
return `CLEANED HTML FROM [${url}]:
|
|
1628
1640
|
|
|
@@ -1736,24 +1748,24 @@ var init_chat = __esm({
|
|
|
1736
1748
|
});
|
|
1737
1749
|
|
|
1738
1750
|
// src/tools/list_files.js
|
|
1739
|
-
import
|
|
1740
|
-
import
|
|
1751
|
+
import fs7 from "fs";
|
|
1752
|
+
import path6 from "path";
|
|
1741
1753
|
var list_files;
|
|
1742
1754
|
var init_list_files = __esm({
|
|
1743
1755
|
"src/tools/list_files.js"() {
|
|
1744
1756
|
init_arg_parser();
|
|
1745
1757
|
list_files = async (args) => {
|
|
1746
1758
|
const { path: targetPath = "." } = parseArgs(args);
|
|
1747
|
-
const absolutePath =
|
|
1759
|
+
const absolutePath = path6.resolve(process.cwd(), targetPath);
|
|
1748
1760
|
try {
|
|
1749
|
-
if (!
|
|
1761
|
+
if (!fs7.existsSync(absolutePath)) {
|
|
1750
1762
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
1751
1763
|
}
|
|
1752
|
-
const stats =
|
|
1764
|
+
const stats = fs7.statSync(absolutePath);
|
|
1753
1765
|
if (!stats.isDirectory()) {
|
|
1754
1766
|
return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
|
|
1755
1767
|
}
|
|
1756
|
-
const files =
|
|
1768
|
+
const files = fs7.readdirSync(absolutePath);
|
|
1757
1769
|
if (files.length === 0) {
|
|
1758
1770
|
return `Directory [${targetPath}] is empty.`;
|
|
1759
1771
|
}
|
|
@@ -1761,11 +1773,11 @@ var init_list_files = __esm({
|
|
|
1761
1773
|
const maxDisplay = 100;
|
|
1762
1774
|
const displayFiles = files.slice(0, maxDisplay);
|
|
1763
1775
|
const list = displayFiles.map((file) => {
|
|
1764
|
-
const fPath =
|
|
1776
|
+
const fPath = path6.join(absolutePath, file);
|
|
1765
1777
|
let indicator = "\u{1F4C4}";
|
|
1766
1778
|
let metaPart = "";
|
|
1767
1779
|
try {
|
|
1768
|
-
const fStats =
|
|
1780
|
+
const fStats = fs7.statSync(fPath);
|
|
1769
1781
|
indicator = fStats.isDirectory() ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
1770
1782
|
const sizeKB = (fStats.size / 1024).toFixed(1);
|
|
1771
1783
|
metaPart = fStats.isFile() ? ` - [${sizeKB} KB]` : "";
|
|
@@ -1797,8 +1809,8 @@ ${list}${footer}`;
|
|
|
1797
1809
|
});
|
|
1798
1810
|
|
|
1799
1811
|
// src/tools/view_file.js
|
|
1800
|
-
import
|
|
1801
|
-
import
|
|
1812
|
+
import fs8 from "fs";
|
|
1813
|
+
import path7 from "path";
|
|
1802
1814
|
var view_file;
|
|
1803
1815
|
var init_view_file = __esm({
|
|
1804
1816
|
"src/tools/view_file.js"() {
|
|
@@ -1810,16 +1822,16 @@ var init_view_file = __esm({
|
|
|
1810
1822
|
const finalStart = sLine || 1;
|
|
1811
1823
|
const finalEnd = eLine || (sLine ? sLine + 800 : 800);
|
|
1812
1824
|
if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
|
|
1813
|
-
const absolutePath =
|
|
1825
|
+
const absolutePath = path7.resolve(process.cwd(), targetPath);
|
|
1814
1826
|
try {
|
|
1815
|
-
if (!
|
|
1827
|
+
if (!fs8.existsSync(absolutePath)) {
|
|
1816
1828
|
return `ERROR: File [${targetPath}] does not exist.`;
|
|
1817
1829
|
}
|
|
1818
|
-
const stats =
|
|
1830
|
+
const stats = fs8.statSync(absolutePath);
|
|
1819
1831
|
if (stats.isDirectory()) {
|
|
1820
1832
|
return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
|
|
1821
1833
|
}
|
|
1822
|
-
const ext =
|
|
1834
|
+
const ext = path7.extname(targetPath).toLowerCase();
|
|
1823
1835
|
const mimeMap = {
|
|
1824
1836
|
".pdf": "application/pdf",
|
|
1825
1837
|
".jpg": "image/jpeg",
|
|
@@ -1830,7 +1842,7 @@ var init_view_file = __esm({
|
|
|
1830
1842
|
".doc": "application/msword"
|
|
1831
1843
|
};
|
|
1832
1844
|
if (mimeMap[ext]) {
|
|
1833
|
-
const buffer =
|
|
1845
|
+
const buffer = fs8.readFileSync(absolutePath);
|
|
1834
1846
|
const base64 = buffer.toString("base64");
|
|
1835
1847
|
const mimeType = mimeMap[ext];
|
|
1836
1848
|
return {
|
|
@@ -1843,7 +1855,7 @@ var init_view_file = __esm({
|
|
|
1843
1855
|
}
|
|
1844
1856
|
};
|
|
1845
1857
|
}
|
|
1846
|
-
let content =
|
|
1858
|
+
let content = fs8.readFileSync(absolutePath, "utf8");
|
|
1847
1859
|
if (content.startsWith("\uFEFF")) {
|
|
1848
1860
|
content = content.slice(1);
|
|
1849
1861
|
}
|
|
@@ -1866,8 +1878,8 @@ ${code}`;
|
|
|
1866
1878
|
});
|
|
1867
1879
|
|
|
1868
1880
|
// src/tools/write_file.js
|
|
1869
|
-
import
|
|
1870
|
-
import
|
|
1881
|
+
import fs9 from "fs";
|
|
1882
|
+
import path8 from "path";
|
|
1871
1883
|
var write_file;
|
|
1872
1884
|
var init_write_file = __esm({
|
|
1873
1885
|
"src/tools/write_file.js"() {
|
|
@@ -1877,13 +1889,13 @@ var init_write_file = __esm({
|
|
|
1877
1889
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
|
|
1878
1890
|
if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
|
|
1879
1891
|
content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1880
|
-
const absolutePath =
|
|
1881
|
-
const parentDir =
|
|
1892
|
+
const absolutePath = path8.resolve(process.cwd(), targetPath);
|
|
1893
|
+
const parentDir = path8.dirname(absolutePath);
|
|
1882
1894
|
try {
|
|
1883
1895
|
let ancestry = "";
|
|
1884
|
-
if (
|
|
1896
|
+
if (fs9.existsSync(absolutePath)) {
|
|
1885
1897
|
try {
|
|
1886
|
-
const oldData =
|
|
1898
|
+
const oldData = fs9.readFileSync(absolutePath, "utf8");
|
|
1887
1899
|
const lines = oldData.split(/\r?\n/);
|
|
1888
1900
|
ancestry = `Old File contents:
|
|
1889
1901
|
${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
@@ -1895,15 +1907,15 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
|
|
|
1895
1907
|
`;
|
|
1896
1908
|
}
|
|
1897
1909
|
}
|
|
1898
|
-
if (!
|
|
1899
|
-
|
|
1910
|
+
if (!fs9.existsSync(parentDir)) {
|
|
1911
|
+
fs9.mkdirSync(parentDir, { recursive: true });
|
|
1900
1912
|
}
|
|
1901
1913
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1902
1914
|
const processedContent = strip(content);
|
|
1903
1915
|
const lineCount = processedContent.split(/\r?\n/).length;
|
|
1904
1916
|
const originalSize = Buffer.byteLength(processedContent, "utf8");
|
|
1905
|
-
|
|
1906
|
-
let verifiedContent =
|
|
1917
|
+
fs9.writeFileSync(absolutePath, processedContent, "utf8");
|
|
1918
|
+
let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
|
|
1907
1919
|
const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
|
|
1908
1920
|
const verifiedLines = verifiedContent.split(/\r?\n/);
|
|
1909
1921
|
const verifiedLineCount = verifiedLines.length;
|
|
@@ -1939,8 +1951,8 @@ Check if Starting and Ending matches your write.`;
|
|
|
1939
1951
|
});
|
|
1940
1952
|
|
|
1941
1953
|
// src/tools/update_file.js
|
|
1942
|
-
import
|
|
1943
|
-
import
|
|
1954
|
+
import fs10 from "fs";
|
|
1955
|
+
import path9 from "path";
|
|
1944
1956
|
var update_file;
|
|
1945
1957
|
var init_update_file = __esm({
|
|
1946
1958
|
"src/tools/update_file.js"() {
|
|
@@ -1953,18 +1965,18 @@ var init_update_file = __esm({
|
|
|
1953
1965
|
const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1954
1966
|
content_to_replace = strip(content_to_replace);
|
|
1955
1967
|
content_to_add = strip(content_to_add);
|
|
1956
|
-
const absolutePath =
|
|
1968
|
+
const absolutePath = path9.resolve(process.cwd(), targetPath);
|
|
1957
1969
|
try {
|
|
1958
|
-
if (!
|
|
1970
|
+
if (!fs10.existsSync(absolutePath)) {
|
|
1959
1971
|
return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
|
|
1960
1972
|
}
|
|
1961
|
-
let diskContent =
|
|
1973
|
+
let diskContent = fs10.readFileSync(absolutePath, "utf8");
|
|
1962
1974
|
if (diskContent.startsWith("\uFEFF")) {
|
|
1963
1975
|
diskContent = diskContent.slice(1);
|
|
1964
1976
|
}
|
|
1965
1977
|
const normalizedDisk = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1966
1978
|
if (diskContent !== normalizedDisk) {
|
|
1967
|
-
|
|
1979
|
+
fs10.writeFileSync(absolutePath, normalizedDisk, "utf8");
|
|
1968
1980
|
diskContent = normalizedDisk;
|
|
1969
1981
|
}
|
|
1970
1982
|
const currentContent = diskContent;
|
|
@@ -2033,7 +2045,7 @@ var init_update_file = __esm({
|
|
|
2033
2045
|
const firstLeadingContext = currentContent.substring(firstLineStart, startPos);
|
|
2034
2046
|
const finalContentToAdd = adjustIndentation(content_to_add, firstMatchContent, firstLeadingContext);
|
|
2035
2047
|
const finalContentToReplace = firstMatchContent;
|
|
2036
|
-
|
|
2048
|
+
fs10.writeFileSync(absolutePath, newFileContent, "utf8");
|
|
2037
2049
|
const allOriginalLines = currentContent.split(/\r?\n/);
|
|
2038
2050
|
const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
|
|
2039
2051
|
const oldLines = content_to_replace.split(/\r?\n/);
|
|
@@ -2296,34 +2308,34 @@ ${finalOutput}`);
|
|
|
2296
2308
|
});
|
|
2297
2309
|
|
|
2298
2310
|
// src/tools/read_folder.js
|
|
2299
|
-
import
|
|
2300
|
-
import
|
|
2311
|
+
import fs11 from "fs";
|
|
2312
|
+
import path10 from "path";
|
|
2301
2313
|
var read_folder;
|
|
2302
2314
|
var init_read_folder = __esm({
|
|
2303
2315
|
"src/tools/read_folder.js"() {
|
|
2304
2316
|
init_arg_parser();
|
|
2305
2317
|
read_folder = async (args) => {
|
|
2306
2318
|
const { path: targetPath = "." } = parseArgs(args);
|
|
2307
|
-
const absolutePath =
|
|
2319
|
+
const absolutePath = path10.resolve(process.cwd(), targetPath);
|
|
2308
2320
|
try {
|
|
2309
|
-
if (!
|
|
2321
|
+
if (!fs11.existsSync(absolutePath)) {
|
|
2310
2322
|
return `ERROR: Path [${targetPath}] does not exist.`;
|
|
2311
2323
|
}
|
|
2312
|
-
const stats =
|
|
2324
|
+
const stats = fs11.statSync(absolutePath);
|
|
2313
2325
|
if (!stats.isDirectory()) {
|
|
2314
2326
|
return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
|
|
2315
2327
|
}
|
|
2316
|
-
const files =
|
|
2328
|
+
const files = fs11.readdirSync(absolutePath);
|
|
2317
2329
|
const totalItems = files.length;
|
|
2318
2330
|
const maxDisplay = 100;
|
|
2319
2331
|
const displayItems = files.slice(0, maxDisplay);
|
|
2320
2332
|
const folderData = [];
|
|
2321
2333
|
for (const file of displayItems) {
|
|
2322
|
-
const fPath =
|
|
2334
|
+
const fPath = path10.join(absolutePath, file);
|
|
2323
2335
|
let indicator = "\u{1F4C4}";
|
|
2324
2336
|
let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
|
|
2325
2337
|
try {
|
|
2326
|
-
const fStats =
|
|
2338
|
+
const fStats = fs11.statSync(fPath);
|
|
2327
2339
|
info = {
|
|
2328
2340
|
name: file,
|
|
2329
2341
|
type: fStats.isDirectory() ? "directory" : "file",
|
|
@@ -2406,8 +2418,8 @@ var init_ask_user = __esm({
|
|
|
2406
2418
|
|
|
2407
2419
|
// src/tools/write_pdf.js
|
|
2408
2420
|
import puppeteer3 from "puppeteer";
|
|
2409
|
-
import
|
|
2410
|
-
import
|
|
2421
|
+
import path11 from "path";
|
|
2422
|
+
import fs12 from "fs-extra";
|
|
2411
2423
|
import { PDFDocument } from "pdf-lib";
|
|
2412
2424
|
var write_pdf;
|
|
2413
2425
|
var init_write_pdf = __esm({
|
|
@@ -2422,10 +2434,10 @@ var init_write_pdf = __esm({
|
|
|
2422
2434
|
} = parseArgs(args);
|
|
2423
2435
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
|
|
2424
2436
|
if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
|
|
2425
|
-
const absolutePath =
|
|
2437
|
+
const absolutePath = path11.resolve(process.cwd(), targetPath);
|
|
2426
2438
|
let browser = null;
|
|
2427
2439
|
try {
|
|
2428
|
-
await
|
|
2440
|
+
await fs12.ensureDir(path11.dirname(absolutePath));
|
|
2429
2441
|
browser = await puppeteer3.launch({
|
|
2430
2442
|
headless: true,
|
|
2431
2443
|
args: [
|
|
@@ -2480,7 +2492,7 @@ var init_write_pdf = __esm({
|
|
|
2480
2492
|
printBackground: true
|
|
2481
2493
|
});
|
|
2482
2494
|
const pdfDoc = await PDFDocument.load(pdfBytes);
|
|
2483
|
-
const fileName =
|
|
2495
|
+
const fileName = path11.basename(targetPath);
|
|
2484
2496
|
pdfDoc.setTitle(`FluxFlow_${fileName}`);
|
|
2485
2497
|
pdfDoc.setAuthor("FluxFlow CLI");
|
|
2486
2498
|
pdfDoc.setSubject("Generated with Agentic AI System");
|
|
@@ -2488,8 +2500,8 @@ var init_write_pdf = __esm({
|
|
|
2488
2500
|
pdfDoc.setCreator("FluxFlow PDF Engine");
|
|
2489
2501
|
pdfDoc.setProducer("FluxFlow (Generative AI)");
|
|
2490
2502
|
const finalPdfBytes = await pdfDoc.save();
|
|
2491
|
-
await
|
|
2492
|
-
const stats = await
|
|
2503
|
+
await fs12.writeFile(absolutePath, finalPdfBytes);
|
|
2504
|
+
const stats = await fs12.stat(absolutePath);
|
|
2493
2505
|
return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
|
|
2494
2506
|
} catch (err) {
|
|
2495
2507
|
return `ERROR: Failed to generate PDF [${targetPath}]: ${err.message}`;
|
|
@@ -2501,8 +2513,8 @@ var init_write_pdf = __esm({
|
|
|
2501
2513
|
});
|
|
2502
2514
|
|
|
2503
2515
|
// src/tools/write_docx.js
|
|
2504
|
-
import
|
|
2505
|
-
import
|
|
2516
|
+
import fs13 from "fs-extra";
|
|
2517
|
+
import path12 from "path";
|
|
2506
2518
|
import HTMLtoDOCX from "html-to-docx";
|
|
2507
2519
|
var write_docx;
|
|
2508
2520
|
var init_write_docx = __esm({
|
|
@@ -2515,10 +2527,10 @@ var init_write_docx = __esm({
|
|
|
2515
2527
|
} = parseArgs(args);
|
|
2516
2528
|
if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
|
|
2517
2529
|
if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
|
|
2518
|
-
const absolutePath =
|
|
2530
|
+
const absolutePath = path12.resolve(process.cwd(), targetPath);
|
|
2519
2531
|
try {
|
|
2520
|
-
await
|
|
2521
|
-
const fileName =
|
|
2532
|
+
await fs13.ensureDir(path12.dirname(absolutePath));
|
|
2533
|
+
const fileName = path12.basename(targetPath);
|
|
2522
2534
|
const fullHtml = content.includes("<html") ? content : `
|
|
2523
2535
|
<!DOCTYPE html>
|
|
2524
2536
|
<html lang="en">
|
|
@@ -2539,7 +2551,7 @@ var init_write_docx = __esm({
|
|
|
2539
2551
|
footer: true,
|
|
2540
2552
|
pageNumber: true
|
|
2541
2553
|
});
|
|
2542
|
-
await
|
|
2554
|
+
await fs13.writeFile(absolutePath, docxBuffer);
|
|
2543
2555
|
return `SUCCESS: Word document [${targetPath}] generated successfully.
|
|
2544
2556
|
- Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
|
|
2545
2557
|
} catch (err) {
|
|
@@ -2605,6 +2617,269 @@ var init_search_keyword = __esm({
|
|
|
2605
2617
|
}
|
|
2606
2618
|
});
|
|
2607
2619
|
|
|
2620
|
+
// src/utils/settings.js
|
|
2621
|
+
import fs14 from "fs-extra";
|
|
2622
|
+
import path13 from "path";
|
|
2623
|
+
var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
|
|
2624
|
+
var init_settings = __esm({
|
|
2625
|
+
"src/utils/settings.js"() {
|
|
2626
|
+
init_paths();
|
|
2627
|
+
DEFAULT_SETTINGS = {
|
|
2628
|
+
mode: "Flux",
|
|
2629
|
+
thinkingLevel: "Medium",
|
|
2630
|
+
activeModel: "gemma-4-31b-it",
|
|
2631
|
+
showFullThinking: true,
|
|
2632
|
+
apiTier: "Free",
|
|
2633
|
+
quotas: {
|
|
2634
|
+
agentLimit: 1500,
|
|
2635
|
+
backgroundLimit: 1500,
|
|
2636
|
+
searchLimit: 100,
|
|
2637
|
+
customModelId: "",
|
|
2638
|
+
customLimit: 0
|
|
2639
|
+
},
|
|
2640
|
+
systemSettings: {
|
|
2641
|
+
memory: true,
|
|
2642
|
+
compression: 0,
|
|
2643
|
+
autoExec: false,
|
|
2644
|
+
allowExternalAccess: false,
|
|
2645
|
+
autoDeleteHistory: "7d",
|
|
2646
|
+
useExternalData: false,
|
|
2647
|
+
externalDataPath: ""
|
|
2648
|
+
},
|
|
2649
|
+
profileData: {
|
|
2650
|
+
name: null,
|
|
2651
|
+
nickname: null,
|
|
2652
|
+
instructions: null
|
|
2653
|
+
},
|
|
2654
|
+
imageSettings: {
|
|
2655
|
+
keyType: "Default",
|
|
2656
|
+
quality: "Low-High",
|
|
2657
|
+
apiKey: ""
|
|
2658
|
+
}
|
|
2659
|
+
};
|
|
2660
|
+
loadSettings = async () => {
|
|
2661
|
+
try {
|
|
2662
|
+
if (await fs14.exists(SETTINGS_FILE)) {
|
|
2663
|
+
const saved = await fs14.readJson(SETTINGS_FILE);
|
|
2664
|
+
const merged = {
|
|
2665
|
+
...DEFAULT_SETTINGS,
|
|
2666
|
+
...saved,
|
|
2667
|
+
quotas: { ...DEFAULT_SETTINGS.quotas, ...saved.quotas },
|
|
2668
|
+
systemSettings: { ...DEFAULT_SETTINGS.systemSettings, ...saved.systemSettings },
|
|
2669
|
+
profileData: { ...DEFAULT_SETTINGS.profileData, ...saved.profileData },
|
|
2670
|
+
imageSettings: { ...DEFAULT_SETTINGS.imageSettings, ...saved.imageSettings }
|
|
2671
|
+
};
|
|
2672
|
+
if (merged.showFullThinking === false) {
|
|
2673
|
+
merged.showFullThinking = true;
|
|
2674
|
+
await fs14.writeJson(SETTINGS_FILE, merged, { spaces: 2 });
|
|
2675
|
+
}
|
|
2676
|
+
return merged;
|
|
2677
|
+
}
|
|
2678
|
+
} catch (err) {
|
|
2679
|
+
console.error("Failed to load settings:", err);
|
|
2680
|
+
}
|
|
2681
|
+
return DEFAULT_SETTINGS;
|
|
2682
|
+
};
|
|
2683
|
+
migrateToExternal = async (newPath) => {
|
|
2684
|
+
const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
2685
|
+
const folders = ["logs", "secret"];
|
|
2686
|
+
for (const folder of folders) {
|
|
2687
|
+
const src = path13.join(FLUXFLOW_DIR2, folder);
|
|
2688
|
+
const dest = path13.join(newPath, folder);
|
|
2689
|
+
try {
|
|
2690
|
+
if (await fs14.exists(src)) {
|
|
2691
|
+
await fs14.ensureDir(dest);
|
|
2692
|
+
await fs14.copy(src, dest, { overwrite: true });
|
|
2693
|
+
}
|
|
2694
|
+
} catch (err) {
|
|
2695
|
+
console.error(`Migration failed for ${folder}:`, err);
|
|
2696
|
+
}
|
|
2697
|
+
}
|
|
2698
|
+
};
|
|
2699
|
+
saveSettings = async (settings) => {
|
|
2700
|
+
try {
|
|
2701
|
+
const current = await loadSettings();
|
|
2702
|
+
if (!current.systemSettings.useExternalData && settings.systemSettings?.useExternalData && settings.systemSettings?.externalDataPath) {
|
|
2703
|
+
await migrateToExternal(settings.systemSettings.externalDataPath);
|
|
2704
|
+
}
|
|
2705
|
+
const updated = { ...current, ...settings };
|
|
2706
|
+
await fs14.ensureDir(path13.dirname(SETTINGS_FILE));
|
|
2707
|
+
await fs14.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
|
|
2708
|
+
return true;
|
|
2709
|
+
} catch (err) {
|
|
2710
|
+
console.error("Failed to save settings:", err);
|
|
2711
|
+
return false;
|
|
2712
|
+
}
|
|
2713
|
+
};
|
|
2714
|
+
}
|
|
2715
|
+
});
|
|
2716
|
+
|
|
2717
|
+
// src/tools/generate_image.js
|
|
2718
|
+
import fs15 from "fs-extra";
|
|
2719
|
+
import path14 from "path";
|
|
2720
|
+
var injectPngMetadata, generate_image;
|
|
2721
|
+
var init_generate_image = __esm({
|
|
2722
|
+
"src/tools/generate_image.js"() {
|
|
2723
|
+
init_arg_parser();
|
|
2724
|
+
init_settings();
|
|
2725
|
+
init_usage();
|
|
2726
|
+
injectPngMetadata = (buffer, metadata = {}) => {
|
|
2727
|
+
try {
|
|
2728
|
+
if (buffer.length < 8 || buffer[0] !== 137 || buffer[1] !== 80 || buffer[2] !== 78 || buffer[3] !== 71) {
|
|
2729
|
+
return buffer;
|
|
2730
|
+
}
|
|
2731
|
+
const chunksToInject = [];
|
|
2732
|
+
const crcTable = [];
|
|
2733
|
+
for (let n = 0; n < 256; n++) {
|
|
2734
|
+
let c = n;
|
|
2735
|
+
for (let k = 0; k < 8; k++) {
|
|
2736
|
+
if (c & 1) {
|
|
2737
|
+
c = 3988292384 ^ c >>> 1;
|
|
2738
|
+
} else {
|
|
2739
|
+
c = c >>> 1;
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
crcTable[n] = c;
|
|
2743
|
+
}
|
|
2744
|
+
const calculateCrc = (buf) => {
|
|
2745
|
+
let crc = 4294967295;
|
|
2746
|
+
for (let i = 0; i < buf.length; i++) {
|
|
2747
|
+
crc = crcTable[(crc ^ buf[i]) & 255] ^ crc >>> 8;
|
|
2748
|
+
}
|
|
2749
|
+
return (crc ^ 4294967295) >>> 0;
|
|
2750
|
+
};
|
|
2751
|
+
const createTextChunk = (keyword, text) => {
|
|
2752
|
+
const keywordBuf = Buffer.from(keyword, "ascii");
|
|
2753
|
+
const textBuf = Buffer.from(text, "utf-8");
|
|
2754
|
+
const dataLength = keywordBuf.length + 1 + textBuf.length;
|
|
2755
|
+
const chunkBuf = Buffer.alloc(4 + 4 + dataLength + 4);
|
|
2756
|
+
chunkBuf.writeUInt32BE(dataLength, 0);
|
|
2757
|
+
chunkBuf.write("tEXt", 4, "ascii");
|
|
2758
|
+
keywordBuf.copy(chunkBuf, 8);
|
|
2759
|
+
chunkBuf[8 + keywordBuf.length] = 0;
|
|
2760
|
+
textBuf.copy(chunkBuf, 8 + keywordBuf.length + 1);
|
|
2761
|
+
const crcValue = calculateCrc(chunkBuf.subarray(4, 8 + dataLength));
|
|
2762
|
+
chunkBuf.writeUInt32BE(crcValue, 8 + dataLength);
|
|
2763
|
+
return chunkBuf;
|
|
2764
|
+
};
|
|
2765
|
+
for (const [key, val] of Object.entries(metadata)) {
|
|
2766
|
+
if (val !== void 0 && val !== null) {
|
|
2767
|
+
chunksToInject.push(createTextChunk(key, String(val)));
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
if (chunksToInject.length === 0) return buffer;
|
|
2771
|
+
if (buffer.subarray(12, 16).toString("ascii") === "IHDR") {
|
|
2772
|
+
const headerEnd = 33;
|
|
2773
|
+
const before = buffer.subarray(0, headerEnd);
|
|
2774
|
+
const after = buffer.subarray(headerEnd);
|
|
2775
|
+
return Buffer.concat([before, ...chunksToInject, after]);
|
|
2776
|
+
}
|
|
2777
|
+
return buffer;
|
|
2778
|
+
} catch (e) {
|
|
2779
|
+
return buffer;
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
generate_image = async (args) => {
|
|
2783
|
+
const parsed = parseArgs(args);
|
|
2784
|
+
const prompt = parsed.prompt || parsed.text;
|
|
2785
|
+
const outputPath = parsed.path || parsed.outputPath || parsed.output || "generated_image.png";
|
|
2786
|
+
const ratio = parsed.ratio;
|
|
2787
|
+
if (!prompt) {
|
|
2788
|
+
return 'ERROR: Missing "prompt" argument for generate_image.';
|
|
2789
|
+
}
|
|
2790
|
+
try {
|
|
2791
|
+
const settings = await loadSettings();
|
|
2792
|
+
const hasQuota = await checkImageQuota(settings);
|
|
2793
|
+
if (!hasQuota) {
|
|
2794
|
+
return "ERROR: Insufficient Quota for selected quality. Either reduce quality for wait for next refresh cycle.";
|
|
2795
|
+
}
|
|
2796
|
+
const imageSettings = settings.imageSettings || { keyType: "Default", quality: "Low-High", apiKey: "" };
|
|
2797
|
+
const apiKey = imageSettings.keyType === "Custom" && imageSettings.apiKey ? imageSettings.apiKey : "pk_5i7Doib5fATyAN4i";
|
|
2798
|
+
const qualityMap = {
|
|
2799
|
+
"Low": "flux",
|
|
2800
|
+
"Low-High": "zimage",
|
|
2801
|
+
"Medium": "gptimage",
|
|
2802
|
+
"Medium-High": "gptimage",
|
|
2803
|
+
"High": "qwen-image",
|
|
2804
|
+
"Ultra": "gptimage-large",
|
|
2805
|
+
"Premium": "nanobanana-pro"
|
|
2806
|
+
};
|
|
2807
|
+
const selectedModel = qualityMap[imageSettings.quality] || "zimage";
|
|
2808
|
+
let width = 1024;
|
|
2809
|
+
let height = 1024;
|
|
2810
|
+
if (ratio) {
|
|
2811
|
+
const cleanRatio = ratio.replace(/\s+/g, "");
|
|
2812
|
+
if (cleanRatio === "16:9") {
|
|
2813
|
+
width = 1024;
|
|
2814
|
+
height = 576;
|
|
2815
|
+
} else if (cleanRatio === "9:16") {
|
|
2816
|
+
width = 576;
|
|
2817
|
+
height = 1024;
|
|
2818
|
+
} else if (cleanRatio === "4:3") {
|
|
2819
|
+
width = 1024;
|
|
2820
|
+
height = 768;
|
|
2821
|
+
} else if (cleanRatio === "3:4") {
|
|
2822
|
+
width = 768;
|
|
2823
|
+
height = 1024;
|
|
2824
|
+
} else if (cleanRatio === "1:1") {
|
|
2825
|
+
width = 1024;
|
|
2826
|
+
height = 1024;
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
const seed = Math.floor(Math.random() * 1e7);
|
|
2830
|
+
const url = `https://gen.pollinations.ai/image/${encodeURIComponent(prompt)}?model=${selectedModel}&width=${width}&height=${height}&seed=${seed}`;
|
|
2831
|
+
const response = await fetch(url, {
|
|
2832
|
+
method: "GET",
|
|
2833
|
+
headers: {
|
|
2834
|
+
"Authorization": `Bearer ${apiKey}`
|
|
2835
|
+
}
|
|
2836
|
+
});
|
|
2837
|
+
if (!response.ok) {
|
|
2838
|
+
const status = response.status;
|
|
2839
|
+
let errorText = "";
|
|
2840
|
+
try {
|
|
2841
|
+
errorText = await response.text();
|
|
2842
|
+
} catch (e) {
|
|
2843
|
+
}
|
|
2844
|
+
if (status === 402 || errorText.includes("Insufficient balance") || errorText.includes("PAYMENT_REQUIRED")) {
|
|
2845
|
+
return "ERROR: Image Generation Currently unavailable. Try again later.";
|
|
2846
|
+
}
|
|
2847
|
+
return `ERROR: Image Generation failed with status [${status}]: ${errorText || "Unknown API Error"}`;
|
|
2848
|
+
}
|
|
2849
|
+
const contentType = response.headers.get("content-type") || "";
|
|
2850
|
+
if (contentType.includes("application/json")) {
|
|
2851
|
+
const json = await response.json();
|
|
2852
|
+
if (json.status === 402 || json.error && json.error.code === "PAYMENT_REQUIRED") {
|
|
2853
|
+
return "ERROR: Image Generation Currently unavailable. Try again later.";
|
|
2854
|
+
}
|
|
2855
|
+
return `ERROR: Image Generation failed: ${json.error?.message || JSON.stringify(json)}`;
|
|
2856
|
+
}
|
|
2857
|
+
const buffer = await response.arrayBuffer();
|
|
2858
|
+
let finalBuffer = Buffer.from(buffer);
|
|
2859
|
+
const metadata = {
|
|
2860
|
+
"Title": prompt,
|
|
2861
|
+
"Description": "Generated via FluxFlow CLI",
|
|
2862
|
+
"Software": "FluxFlow CLI",
|
|
2863
|
+
"Author": "FluxFlow",
|
|
2864
|
+
"Creation Time": (/* @__PURE__ */ new Date()).toISOString(),
|
|
2865
|
+
"Prompt": prompt,
|
|
2866
|
+
"Model": `Fluxflow:${selectedModel}`,
|
|
2867
|
+
"Ratio": ratio || "1:1",
|
|
2868
|
+
"Seed": String(seed)
|
|
2869
|
+
};
|
|
2870
|
+
finalBuffer = injectPngMetadata(finalBuffer, metadata);
|
|
2871
|
+
const absolutePath = path14.resolve(process.cwd(), outputPath);
|
|
2872
|
+
await fs15.ensureDir(path14.dirname(absolutePath));
|
|
2873
|
+
await fs15.writeFile(absolutePath, finalBuffer);
|
|
2874
|
+
await recordImageGeneration(settings);
|
|
2875
|
+
return `SUCCESS: Image successfully generated from prompt [${prompt}] and saved to [${outputPath}] with custom embedded metadata.`;
|
|
2876
|
+
} catch (err) {
|
|
2877
|
+
return `ERROR: Failed during image generation: ${err.message}`;
|
|
2878
|
+
}
|
|
2879
|
+
};
|
|
2880
|
+
}
|
|
2881
|
+
});
|
|
2882
|
+
|
|
2608
2883
|
// src/utils/tools.js
|
|
2609
2884
|
var TOOL_MAP, dispatchTool;
|
|
2610
2885
|
var init_tools = __esm({
|
|
@@ -2623,6 +2898,7 @@ var init_tools = __esm({
|
|
|
2623
2898
|
init_write_pdf();
|
|
2624
2899
|
init_write_docx();
|
|
2625
2900
|
init_search_keyword();
|
|
2901
|
+
init_generate_image();
|
|
2626
2902
|
TOOL_MAP = {
|
|
2627
2903
|
web_search,
|
|
2628
2904
|
web_scrape,
|
|
@@ -2637,6 +2913,7 @@ var init_tools = __esm({
|
|
|
2637
2913
|
write_pdf,
|
|
2638
2914
|
write_docx,
|
|
2639
2915
|
search_keyword,
|
|
2916
|
+
generate_image,
|
|
2640
2917
|
ask: ask_user,
|
|
2641
2918
|
// PascalCase Normalizations for Token Efficiency
|
|
2642
2919
|
Ask: ask_user,
|
|
@@ -2651,7 +2928,8 @@ var init_tools = __esm({
|
|
|
2651
2928
|
Run: exec_command,
|
|
2652
2929
|
SearchKeyword: search_keyword,
|
|
2653
2930
|
Memory: memory,
|
|
2654
|
-
Chat: chat
|
|
2931
|
+
Chat: chat,
|
|
2932
|
+
GenerateImage: generate_image
|
|
2655
2933
|
};
|
|
2656
2934
|
dispatchTool = async (toolName, args, context = {}) => {
|
|
2657
2935
|
const tool = TOOL_MAP[toolName];
|
|
@@ -2699,7 +2977,8 @@ var init_ai = __esm({
|
|
|
2699
2977
|
"search_keyword": "Finding Files",
|
|
2700
2978
|
"ask": "Asking User",
|
|
2701
2979
|
"write_pdf": "Creating PDF",
|
|
2702
|
-
"write_docx": "Creating Document"
|
|
2980
|
+
"write_docx": "Creating Document",
|
|
2981
|
+
"generate_image": "Generating Image"
|
|
2703
2982
|
};
|
|
2704
2983
|
getToolDetail = (toolName, argsStr) => {
|
|
2705
2984
|
try {
|
|
@@ -2719,10 +2998,18 @@ var init_ai = __esm({
|
|
|
2719
2998
|
const isMemoryEnabled = systemSettings?.memory !== false;
|
|
2720
2999
|
const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
|
|
2721
3000
|
const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
|
|
2722
|
-
const janitorContents = history.slice(-12).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) =>
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
3001
|
+
const janitorContents = history.slice(-12).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => {
|
|
3002
|
+
let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").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();
|
|
3003
|
+
const limit = msg.role === "user" ? 1500 : 24e3;
|
|
3004
|
+
let truncatedText = processedText.substring(0, limit);
|
|
3005
|
+
if (processedText.length > limit) {
|
|
3006
|
+
truncatedText += "\n... (truncated) ...";
|
|
3007
|
+
}
|
|
3008
|
+
return {
|
|
3009
|
+
role: msg.role === "user" ? "user" : "model",
|
|
3010
|
+
parts: [{ text: truncatedText }]
|
|
3011
|
+
};
|
|
3012
|
+
});
|
|
2726
3013
|
const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
2727
3014
|
const janitorPrompt = getJanitorInstruction(
|
|
2728
3015
|
agentText,
|
|
@@ -2737,8 +3024,8 @@ var init_ai = __esm({
|
|
|
2737
3024
|
}
|
|
2738
3025
|
let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
|
|
2739
3026
|
agentRes = agentRes.replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
|
|
2740
|
-
let userPrompt = `[USER]: ${originalTextProcessed.substring(0,
|
|
2741
|
-
${originalTextProcessed.length >
|
|
3027
|
+
let userPrompt = `[USER]: ${originalTextProcessed.substring(0, 1500)}
|
|
3028
|
+
${originalTextProcessed.length > 1500 ? "... (truncated) ...\n\n" : ""}
|
|
2742
3029
|
[AGENT (current turn)]: ${agentRes}`;
|
|
2743
3030
|
janitorContents.push({ role: "user", parts: [{ text: userPrompt }] });
|
|
2744
3031
|
let finalSynthesis = "";
|
|
@@ -3273,7 +3560,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3273
3560
|
"SearchKeyword": "search_keyword",
|
|
3274
3561
|
"Memory": "memory",
|
|
3275
3562
|
"Chat": "chat",
|
|
3276
|
-
"chat": "chat"
|
|
3563
|
+
"chat": "chat",
|
|
3564
|
+
"GenerateImage": "generate_image",
|
|
3565
|
+
"generate_image": "generate_image"
|
|
3277
3566
|
};
|
|
3278
3567
|
const potentialTool = NORMALIZE_MAP[rawToolName] || rawToolName;
|
|
3279
3568
|
const partialArgs = toolContext.args || "";
|
|
@@ -3313,7 +3602,8 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3313
3602
|
"search_keyword": "Searching Keywords",
|
|
3314
3603
|
"exec_command": "Running Command",
|
|
3315
3604
|
"ask": "Asking User",
|
|
3316
|
-
"memory": "Updating Memory"
|
|
3605
|
+
"memory": "Updating Memory",
|
|
3606
|
+
"generate_image": "Generating Image"
|
|
3317
3607
|
};
|
|
3318
3608
|
const toolTitle = TOOL_TITLES[potentialTool] || "Working";
|
|
3319
3609
|
process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
|
|
@@ -3394,7 +3684,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3394
3684
|
"SearchKeyword": "search_keyword",
|
|
3395
3685
|
"Memory": "memory",
|
|
3396
3686
|
"Chat": "chat",
|
|
3397
|
-
"chat": "chat"
|
|
3687
|
+
"chat": "chat",
|
|
3688
|
+
"GenerateImage": "generate_image",
|
|
3689
|
+
"generate_image": "generate_image"
|
|
3398
3690
|
};
|
|
3399
3691
|
const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
|
|
3400
3692
|
const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
|
|
@@ -3448,6 +3740,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3448
3740
|
} else if (normToolName === "search_keyword") {
|
|
3449
3741
|
const { keyword } = parseArgs(toolCall.args);
|
|
3450
3742
|
label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
|
|
3743
|
+
} else if (normToolName === "generate_image") {
|
|
3744
|
+
const { title, prompt, outputPath, output } = parseArgs(toolCall.args);
|
|
3745
|
+
label = `\u{1F3A8} IMAGE GENERATED: "${title || prompt}" -> ${outputPath || output || "generated_image.png"}`.toUpperCase();
|
|
3451
3746
|
} else if (normToolName === "exec_command" || normToolName === "ask") {
|
|
3452
3747
|
label = "";
|
|
3453
3748
|
} else {
|
|
@@ -3509,7 +3804,7 @@ ${boxBottom}` };
|
|
|
3509
3804
|
toolResults.push({ role: "user", text: `[TOOL RESULT]: DENIED: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
|
|
3510
3805
|
yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
|
|
3511
3806
|
await incrementUsage("toolDenied");
|
|
3512
|
-
if (settings.onToolResult) settings.onToolResult("denied");
|
|
3807
|
+
if (settings.onToolResult) settings.onToolResult("denied", normToolName);
|
|
3513
3808
|
toolCallPointer++;
|
|
3514
3809
|
continue;
|
|
3515
3810
|
}
|
|
@@ -3543,11 +3838,11 @@ ${boxBottom}` };
|
|
|
3543
3838
|
const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
|
|
3544
3839
|
if (isSuccess) {
|
|
3545
3840
|
await incrementUsage("toolSuccess");
|
|
3546
|
-
if (settings.onToolResult) settings.onToolResult("success");
|
|
3841
|
+
if (settings.onToolResult) settings.onToolResult("success", normToolName);
|
|
3547
3842
|
} else if (isDenied) {
|
|
3548
3843
|
} else {
|
|
3549
3844
|
await incrementUsage("toolFailure");
|
|
3550
|
-
if (settings.onToolResult) settings.onToolResult("failure");
|
|
3845
|
+
if (settings.onToolResult) settings.onToolResult("failure", normToolName);
|
|
3551
3846
|
}
|
|
3552
3847
|
const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
|
|
3553
3848
|
toolResults.push({ role: "user", text: aiContent, binaryPart });
|
|
@@ -3692,97 +3987,6 @@ ${timestamp}`;
|
|
|
3692
3987
|
}
|
|
3693
3988
|
});
|
|
3694
3989
|
|
|
3695
|
-
// src/utils/settings.js
|
|
3696
|
-
import fs17 from "fs-extra";
|
|
3697
|
-
import path16 from "path";
|
|
3698
|
-
var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
|
|
3699
|
-
var init_settings = __esm({
|
|
3700
|
-
"src/utils/settings.js"() {
|
|
3701
|
-
init_paths();
|
|
3702
|
-
DEFAULT_SETTINGS = {
|
|
3703
|
-
mode: "Flux",
|
|
3704
|
-
thinkingLevel: "Medium",
|
|
3705
|
-
activeModel: "gemma-4-31b-it",
|
|
3706
|
-
showFullThinking: true,
|
|
3707
|
-
apiTier: "Free",
|
|
3708
|
-
quotas: {
|
|
3709
|
-
agentLimit: 1500,
|
|
3710
|
-
backgroundLimit: 1500,
|
|
3711
|
-
searchLimit: 100,
|
|
3712
|
-
customModelId: "",
|
|
3713
|
-
customLimit: 0
|
|
3714
|
-
},
|
|
3715
|
-
systemSettings: {
|
|
3716
|
-
memory: true,
|
|
3717
|
-
compression: 0,
|
|
3718
|
-
autoExec: false,
|
|
3719
|
-
allowExternalAccess: false,
|
|
3720
|
-
autoDeleteHistory: "7d",
|
|
3721
|
-
useExternalData: false,
|
|
3722
|
-
externalDataPath: ""
|
|
3723
|
-
},
|
|
3724
|
-
profileData: {
|
|
3725
|
-
name: null,
|
|
3726
|
-
nickname: null,
|
|
3727
|
-
instructions: null
|
|
3728
|
-
}
|
|
3729
|
-
};
|
|
3730
|
-
loadSettings = async () => {
|
|
3731
|
-
try {
|
|
3732
|
-
if (await fs17.exists(SETTINGS_FILE)) {
|
|
3733
|
-
const saved = await fs17.readJson(SETTINGS_FILE);
|
|
3734
|
-
const merged = {
|
|
3735
|
-
...DEFAULT_SETTINGS,
|
|
3736
|
-
...saved,
|
|
3737
|
-
quotas: { ...DEFAULT_SETTINGS.quotas, ...saved.quotas },
|
|
3738
|
-
systemSettings: { ...DEFAULT_SETTINGS.systemSettings, ...saved.systemSettings },
|
|
3739
|
-
profileData: { ...DEFAULT_SETTINGS.profileData, ...saved.profileData }
|
|
3740
|
-
};
|
|
3741
|
-
if (merged.showFullThinking === false) {
|
|
3742
|
-
merged.showFullThinking = true;
|
|
3743
|
-
await fs17.writeJson(SETTINGS_FILE, merged, { spaces: 2 });
|
|
3744
|
-
}
|
|
3745
|
-
return merged;
|
|
3746
|
-
}
|
|
3747
|
-
} catch (err) {
|
|
3748
|
-
console.error("Failed to load settings:", err);
|
|
3749
|
-
}
|
|
3750
|
-
return DEFAULT_SETTINGS;
|
|
3751
|
-
};
|
|
3752
|
-
migrateToExternal = async (newPath) => {
|
|
3753
|
-
const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
3754
|
-
const folders = ["logs", "secret"];
|
|
3755
|
-
for (const folder of folders) {
|
|
3756
|
-
const src = path16.join(FLUXFLOW_DIR2, folder);
|
|
3757
|
-
const dest = path16.join(newPath, folder);
|
|
3758
|
-
try {
|
|
3759
|
-
if (await fs17.exists(src)) {
|
|
3760
|
-
await fs17.ensureDir(dest);
|
|
3761
|
-
await fs17.copy(src, dest, { overwrite: true });
|
|
3762
|
-
}
|
|
3763
|
-
} catch (err) {
|
|
3764
|
-
console.error(`Migration failed for ${folder}:`, err);
|
|
3765
|
-
}
|
|
3766
|
-
}
|
|
3767
|
-
};
|
|
3768
|
-
saveSettings = async (settings) => {
|
|
3769
|
-
try {
|
|
3770
|
-
const current = await loadSettings();
|
|
3771
|
-
if (!current.systemSettings.useExternalData && settings.systemSettings?.useExternalData && settings.systemSettings?.externalDataPath) {
|
|
3772
|
-
await migrateToExternal(settings.systemSettings.externalDataPath);
|
|
3773
|
-
}
|
|
3774
|
-
const updated = { ...current, ...settings };
|
|
3775
|
-
await fs17.ensureDir(path16.dirname(SETTINGS_FILE));
|
|
3776
|
-
await fs17.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
|
|
3777
|
-
return true;
|
|
3778
|
-
} catch (err) {
|
|
3779
|
-
console.error("Failed to save settings:", err);
|
|
3780
|
-
return false;
|
|
3781
|
-
}
|
|
3782
|
-
};
|
|
3783
|
-
}
|
|
3784
|
-
});
|
|
3785
|
-
|
|
3786
3990
|
// src/components/ResumeModal.jsx
|
|
3787
3991
|
import React7, { useState as useState4, useEffect as useEffect2 } from "react";
|
|
3788
3992
|
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
@@ -3986,7 +4190,7 @@ var init_UpdateProcessor = __esm({
|
|
|
3986
4190
|
import puppeteer4 from "puppeteer";
|
|
3987
4191
|
import { exec as exec3 } from "child_process";
|
|
3988
4192
|
import { promisify } from "util";
|
|
3989
|
-
import
|
|
4193
|
+
import fs17 from "fs";
|
|
3990
4194
|
var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
|
|
3991
4195
|
var init_setup = __esm({
|
|
3992
4196
|
"src/utils/setup.js"() {
|
|
@@ -3994,7 +4198,7 @@ var init_setup = __esm({
|
|
|
3994
4198
|
checkPuppeteerReady = () => {
|
|
3995
4199
|
try {
|
|
3996
4200
|
const exePath = puppeteer4.executablePath();
|
|
3997
|
-
const exists = exePath &&
|
|
4201
|
+
const exists = exePath && fs17.existsSync(exePath);
|
|
3998
4202
|
if (exists) return true;
|
|
3999
4203
|
} catch (e) {
|
|
4000
4204
|
return false;
|
|
@@ -4028,8 +4232,8 @@ import os3 from "os";
|
|
|
4028
4232
|
import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
|
|
4029
4233
|
import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
|
|
4030
4234
|
import Spinner2 from "ink-spinner";
|
|
4031
|
-
import
|
|
4032
|
-
import
|
|
4235
|
+
import fs18 from "fs-extra";
|
|
4236
|
+
import path16 from "path";
|
|
4033
4237
|
import { exec as exec4 } from "child_process";
|
|
4034
4238
|
import { fileURLToPath } from "url";
|
|
4035
4239
|
import { MultilineInput } from "ink-multiline-input";
|
|
@@ -4125,6 +4329,7 @@ function App() {
|
|
|
4125
4329
|
const [inputConfig, setInputConfig] = useState7(null);
|
|
4126
4330
|
const [systemSettings, setSystemSettings] = useState7({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
|
|
4127
4331
|
const [profileData, setProfileData] = useState7({ name: null, nickname: null, instructions: null });
|
|
4332
|
+
const [imageSettings, setImageSettings] = useState7({ keyType: "Default", quality: "Low-High", apiKey: "" });
|
|
4128
4333
|
const [sessionStats, setSessionStats] = useState7({ tokens: 0 });
|
|
4129
4334
|
const [sessionAgentCalls, setSessionAgentCalls] = useState7(0);
|
|
4130
4335
|
const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState7(0);
|
|
@@ -4134,6 +4339,8 @@ function App() {
|
|
|
4134
4339
|
const [sessionToolDenied, setSessionToolDenied] = useState7(0);
|
|
4135
4340
|
const [sessionApiTime, setSessionApiTime] = useState7(0);
|
|
4136
4341
|
const [sessionToolTime, setSessionToolTime] = useState7(0);
|
|
4342
|
+
const [sessionImageCount, setSessionImageCount] = useState7(0);
|
|
4343
|
+
const [sessionImageCredits, setSessionImageCredits] = useState7(0);
|
|
4137
4344
|
const [dailyUsage, setDailyUsage] = useState7(null);
|
|
4138
4345
|
const [chatId, setChatId] = useState7(generateChatId());
|
|
4139
4346
|
const [activeCommand, setActiveCommand] = useState7(null);
|
|
@@ -4383,6 +4590,7 @@ function App() {
|
|
|
4383
4590
|
};
|
|
4384
4591
|
setSystemSettings(freshSettings);
|
|
4385
4592
|
setProfileData(saved.profileData);
|
|
4593
|
+
setImageSettings(saved.imageSettings || { keyType: "Default", quality: "Low-High", apiKey: "" });
|
|
4386
4594
|
const key = await getAPIKey();
|
|
4387
4595
|
if (key) {
|
|
4388
4596
|
setApiKey(key);
|
|
@@ -4423,10 +4631,11 @@ function App() {
|
|
|
4423
4631
|
activeModel,
|
|
4424
4632
|
showFullThinking,
|
|
4425
4633
|
systemSettings,
|
|
4426
|
-
profileData
|
|
4634
|
+
profileData,
|
|
4635
|
+
imageSettings
|
|
4427
4636
|
});
|
|
4428
4637
|
}
|
|
4429
|
-
}, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, isInitializing]);
|
|
4638
|
+
}, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, imageSettings, isInitializing]);
|
|
4430
4639
|
const handleSetup = async (val) => {
|
|
4431
4640
|
const key = val.trim();
|
|
4432
4641
|
if (key.length >= 30) {
|
|
@@ -4478,6 +4687,40 @@ function App() {
|
|
|
4478
4687
|
{ cmd: "/resume", desc: "Load previous session" },
|
|
4479
4688
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
4480
4689
|
{ cmd: "/chats", desc: "List all chat sessions" },
|
|
4690
|
+
{
|
|
4691
|
+
cmd: "/image",
|
|
4692
|
+
desc: "Generate images using Pollinations",
|
|
4693
|
+
subs: [
|
|
4694
|
+
{
|
|
4695
|
+
cmd: "setup",
|
|
4696
|
+
desc: "Configure defaults",
|
|
4697
|
+
subs: [
|
|
4698
|
+
{
|
|
4699
|
+
cmd: "key",
|
|
4700
|
+
desc: "Set API key strategy",
|
|
4701
|
+
subs: [
|
|
4702
|
+
{ cmd: "default", desc: "Default (Quota: 0.020 credits/hr)" },
|
|
4703
|
+
{ cmd: "custom", desc: "Custom Key" }
|
|
4704
|
+
]
|
|
4705
|
+
},
|
|
4706
|
+
{
|
|
4707
|
+
cmd: "quality",
|
|
4708
|
+
desc: "Set default quality",
|
|
4709
|
+
subs: [
|
|
4710
|
+
{ cmd: "low", desc: "(0.001/img)" },
|
|
4711
|
+
{ cmd: "low-high", desc: "(0.002/img)" },
|
|
4712
|
+
{ cmd: "medium", desc: "(0.008/img)" },
|
|
4713
|
+
{ cmd: "medium-high", desc: "(0.01/img)" },
|
|
4714
|
+
{ cmd: "high", desc: "(0.045/img)" },
|
|
4715
|
+
{ cmd: "ultra", desc: "(0.0488/img)" },
|
|
4716
|
+
{ cmd: "premium", desc: "(0.1/img)" }
|
|
4717
|
+
]
|
|
4718
|
+
}
|
|
4719
|
+
]
|
|
4720
|
+
},
|
|
4721
|
+
{ cmd: "stats", desc: "Show remaining credits or Pollinations balance status" }
|
|
4722
|
+
]
|
|
4723
|
+
},
|
|
4481
4724
|
{
|
|
4482
4725
|
cmd: "/mode",
|
|
4483
4726
|
desc: "Toggle Flux/Flow modes",
|
|
@@ -4531,14 +4774,15 @@ function App() {
|
|
|
4531
4774
|
]
|
|
4532
4775
|
}
|
|
4533
4776
|
];
|
|
4534
|
-
const handleSubmit = (value) => {
|
|
4777
|
+
const handleSubmit = async (value) => {
|
|
4535
4778
|
if (suggestions.length > 0) {
|
|
4536
4779
|
const nextMatch = suggestions[selectedIndex] || suggestions[0];
|
|
4537
4780
|
const parts = value.split(" ");
|
|
4538
4781
|
if (parts.length === 1) {
|
|
4539
4782
|
setInput(nextMatch.cmd + " ");
|
|
4540
4783
|
} else {
|
|
4541
|
-
|
|
4784
|
+
const parentParts = parts.slice(0, -1);
|
|
4785
|
+
setInput(parentParts.join(" ") + " " + nextMatch.cmd + " ");
|
|
4542
4786
|
}
|
|
4543
4787
|
setSelectedIndex(0);
|
|
4544
4788
|
return;
|
|
@@ -4637,6 +4881,135 @@ ${hintText}`, color: "magenta" }];
|
|
|
4637
4881
|
}
|
|
4638
4882
|
break;
|
|
4639
4883
|
}
|
|
4884
|
+
case "/image": {
|
|
4885
|
+
if (parts[1]?.toLowerCase() === "stats") {
|
|
4886
|
+
const s2 = emojiSpace(2);
|
|
4887
|
+
if (imageSettings.keyType === "Custom") {
|
|
4888
|
+
setMessages((prev) => {
|
|
4889
|
+
setCompletedIndex(prev.length + 1);
|
|
4890
|
+
return [...prev, {
|
|
4891
|
+
id: Date.now(),
|
|
4892
|
+
role: "system",
|
|
4893
|
+
text: `\u{1F517}${s2}[SYSTEM] Key strategy is Custom. Redirecting to Pollinations dashboard (https://enter.pollinations.ai/#pollen)...`,
|
|
4894
|
+
isMeta: true
|
|
4895
|
+
}];
|
|
4896
|
+
});
|
|
4897
|
+
exec4("start https://enter.pollinations.ai/#pollen");
|
|
4898
|
+
} else {
|
|
4899
|
+
try {
|
|
4900
|
+
const stats = await getImageQuotaStats();
|
|
4901
|
+
setMessages((prev) => {
|
|
4902
|
+
setCompletedIndex(prev.length + 1);
|
|
4903
|
+
return [...prev, {
|
|
4904
|
+
id: Date.now(),
|
|
4905
|
+
role: "system",
|
|
4906
|
+
isImageStats: true,
|
|
4907
|
+
text: `\u2022 Hourly Limit: 0.0200 credits
|
|
4908
|
+
\u2022 Spent (Last 1hr): ${stats.totalSpent.toFixed(4)} credits
|
|
4909
|
+
\u2022 Remaining: ${stats.remaining.toFixed(4)} credits
|
|
4910
|
+
\u2022 Requests (Last 1hr): ${stats.activeCallsCount} requests`,
|
|
4911
|
+
isMeta: true
|
|
4912
|
+
}];
|
|
4913
|
+
});
|
|
4914
|
+
} catch (e) {
|
|
4915
|
+
setMessages((prev) => {
|
|
4916
|
+
setCompletedIndex(prev.length + 1);
|
|
4917
|
+
return [...prev, {
|
|
4918
|
+
id: Date.now(),
|
|
4919
|
+
role: "system",
|
|
4920
|
+
text: `\u274C [SYSTEM] Failed to load image quota stats.`,
|
|
4921
|
+
isMeta: true
|
|
4922
|
+
}];
|
|
4923
|
+
});
|
|
4924
|
+
}
|
|
4925
|
+
}
|
|
4926
|
+
} else if (parts[1]?.toLowerCase() === "setup") {
|
|
4927
|
+
if (parts[2]?.toLowerCase() === "key") {
|
|
4928
|
+
if (parts[3]) {
|
|
4929
|
+
const matchedKey = ["default", "custom"].find((k) => k === parts[3].toLowerCase());
|
|
4930
|
+
if (matchedKey) {
|
|
4931
|
+
const strategy = matchedKey === "default" ? "Default" : "Custom";
|
|
4932
|
+
setImageSettings((prev) => ({ ...prev, keyType: strategy }));
|
|
4933
|
+
const s2 = emojiSpace(2);
|
|
4934
|
+
setMessages((prev) => {
|
|
4935
|
+
setCompletedIndex(prev.length + 1);
|
|
4936
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Image key strategy set to ${strategy}`, isMeta: true }];
|
|
4937
|
+
});
|
|
4938
|
+
if (strategy === "Custom") {
|
|
4939
|
+
setInputConfig({
|
|
4940
|
+
label: "Enter Pollinations API key (starting with sk_):",
|
|
4941
|
+
note: "Get a key from https://enter.pollinations.ai",
|
|
4942
|
+
key: "imageSettings",
|
|
4943
|
+
subKey: "apiKey",
|
|
4944
|
+
value: imageSettings.apiKey || "",
|
|
4945
|
+
returnView: "chat"
|
|
4946
|
+
});
|
|
4947
|
+
setActiveView("input");
|
|
4948
|
+
}
|
|
4949
|
+
} else {
|
|
4950
|
+
const s2 = emojiSpace(2);
|
|
4951
|
+
setMessages((prev) => {
|
|
4952
|
+
setCompletedIndex(prev.length + 1);
|
|
4953
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Invalid key option. Choose: Default or Custom.`, isMeta: true }];
|
|
4954
|
+
});
|
|
4955
|
+
}
|
|
4956
|
+
} else {
|
|
4957
|
+
const s2 = emojiSpace(2);
|
|
4958
|
+
setMessages((prev) => {
|
|
4959
|
+
setCompletedIndex(prev.length + 1);
|
|
4960
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Usage: /image setup Key <Default|Custom>`, isMeta: true }];
|
|
4961
|
+
});
|
|
4962
|
+
}
|
|
4963
|
+
} else if (parts[2]?.toLowerCase() === "quality") {
|
|
4964
|
+
if (parts[3]) {
|
|
4965
|
+
const matched = ["low", "low-high", "medium", "medium-high", "high", "ultra", "premium"].find((q) => q === parts[3].toLowerCase());
|
|
4966
|
+
if (matched) {
|
|
4967
|
+
const qualityMap = {
|
|
4968
|
+
"low": "Low",
|
|
4969
|
+
"low-high": "Low-High",
|
|
4970
|
+
"medium": "Medium",
|
|
4971
|
+
"medium-high": "Medium-High",
|
|
4972
|
+
"high": "High",
|
|
4973
|
+
"ultra": "Ultra",
|
|
4974
|
+
"premium": "Premium"
|
|
4975
|
+
};
|
|
4976
|
+
const chosenQuality = qualityMap[matched];
|
|
4977
|
+
setImageSettings((prev) => ({ ...prev, quality: chosenQuality }));
|
|
4978
|
+
const s2 = emojiSpace(2);
|
|
4979
|
+
setMessages((prev) => {
|
|
4980
|
+
setCompletedIndex(prev.length + 1);
|
|
4981
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}${s2}[SYSTEM] Image quality set to ${chosenQuality}`, isMeta: true }];
|
|
4982
|
+
});
|
|
4983
|
+
} else {
|
|
4984
|
+
const s2 = emojiSpace(2);
|
|
4985
|
+
setMessages((prev) => {
|
|
4986
|
+
setCompletedIndex(prev.length + 1);
|
|
4987
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Invalid quality level. Choose from: Low, Low-High, Medium, Medium-High, High, Ultra, Premium.`, isMeta: true }];
|
|
4988
|
+
});
|
|
4989
|
+
}
|
|
4990
|
+
} else {
|
|
4991
|
+
const s2 = emojiSpace(2);
|
|
4992
|
+
setMessages((prev) => {
|
|
4993
|
+
setCompletedIndex(prev.length + 1);
|
|
4994
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Usage: /image setup Quality <Low|Low-High|Medium|Medium-High|High|Ultra>`, isMeta: true }];
|
|
4995
|
+
});
|
|
4996
|
+
}
|
|
4997
|
+
} else {
|
|
4998
|
+
const s2 = emojiSpace(2);
|
|
4999
|
+
setMessages((prev) => {
|
|
5000
|
+
setCompletedIndex(prev.length + 1);
|
|
5001
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Usage: /image setup <Key|Quality> ...`, isMeta: true }];
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
} else {
|
|
5005
|
+
const s2 = emojiSpace(2);
|
|
5006
|
+
setMessages((prev) => {
|
|
5007
|
+
setCompletedIndex(prev.length + 1);
|
|
5008
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [SYSTEM] Usage: /image setup <Key|Quality> ...`, isMeta: true }];
|
|
5009
|
+
});
|
|
5010
|
+
}
|
|
5011
|
+
break;
|
|
5012
|
+
}
|
|
4640
5013
|
case "/thinking": {
|
|
4641
5014
|
let formattedLevel;
|
|
4642
5015
|
if (parts[1]) {
|
|
@@ -4744,12 +5117,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4744
5117
|
setCompletedIndex(prev.length + 1);
|
|
4745
5118
|
return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset...", isMeta: true }];
|
|
4746
5119
|
});
|
|
4747
|
-
if (
|
|
4748
|
-
if (
|
|
4749
|
-
if (
|
|
5120
|
+
if (fs18.existsSync(LOGS_DIR)) fs18.removeSync(LOGS_DIR);
|
|
5121
|
+
if (fs18.existsSync(SECRET_DIR)) fs18.removeSync(SECRET_DIR);
|
|
5122
|
+
if (fs18.existsSync(SETTINGS_FILE)) fs18.removeSync(SETTINGS_FILE);
|
|
4750
5123
|
try {
|
|
4751
|
-
const items =
|
|
4752
|
-
if (items.length === 0)
|
|
5124
|
+
const items = fs18.readdirSync(FLUXFLOW_DIR);
|
|
5125
|
+
if (items.length === 0) fs18.removeSync(FLUXFLOW_DIR);
|
|
4753
5126
|
} catch (e) {
|
|
4754
5127
|
}
|
|
4755
5128
|
setTimeout(() => {
|
|
@@ -4806,14 +5179,14 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4806
5179
|
# SKILLS & WORKFLOWS
|
|
4807
5180
|
- [Define custom step-by-step recipes for this project here]
|
|
4808
5181
|
`;
|
|
4809
|
-
const filePath =
|
|
4810
|
-
if (
|
|
5182
|
+
const filePath = path16.join(process.cwd(), "FluxFlow.md");
|
|
5183
|
+
if (fs18.pathExistsSync(filePath)) {
|
|
4811
5184
|
setMessages((prev) => {
|
|
4812
5185
|
setCompletedIndex(prev.length + 1);
|
|
4813
5186
|
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
4814
5187
|
});
|
|
4815
5188
|
} else {
|
|
4816
|
-
|
|
5189
|
+
fs18.writeFileSync(filePath, template);
|
|
4817
5190
|
setMessages((prev) => {
|
|
4818
5191
|
setCompletedIndex(prev.length + 1);
|
|
4819
5192
|
return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "\u2705 [SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
|
|
@@ -4901,10 +5274,28 @@ OUTPUT: ${execOutputRef.current}`;
|
|
|
4901
5274
|
setIsTerminalFocused(false);
|
|
4902
5275
|
setExecOutput("");
|
|
4903
5276
|
},
|
|
4904
|
-
onToolResult: (status) => {
|
|
4905
|
-
if (status === "success")
|
|
4906
|
-
|
|
4907
|
-
|
|
5277
|
+
onToolResult: (status, toolName) => {
|
|
5278
|
+
if (status === "success") {
|
|
5279
|
+
setSessionToolSuccess((prev) => prev + 1);
|
|
5280
|
+
if (toolName === "generate_image") {
|
|
5281
|
+
setSessionImageCount((prev) => prev + 1);
|
|
5282
|
+
const costs = {
|
|
5283
|
+
"Low": 1e-3,
|
|
5284
|
+
"Low-High": 2e-3,
|
|
5285
|
+
"Medium": 8e-3,
|
|
5286
|
+
"Medium-High": 0.01,
|
|
5287
|
+
"High": 0.045,
|
|
5288
|
+
"Ultra": 0.0488,
|
|
5289
|
+
"Premium": 0.1
|
|
5290
|
+
};
|
|
5291
|
+
const cost = costs[imageSettings.quality] || 2e-3;
|
|
5292
|
+
setSessionImageCredits((prev) => prev + cost);
|
|
5293
|
+
}
|
|
5294
|
+
} else if (status === "denied") {
|
|
5295
|
+
setSessionToolDenied((prev) => prev + 1);
|
|
5296
|
+
} else {
|
|
5297
|
+
setSessionToolFailure((prev) => prev + 1);
|
|
5298
|
+
}
|
|
4908
5299
|
},
|
|
4909
5300
|
onToolApproval: async (tool, args) => {
|
|
4910
5301
|
const isAuto = autoAcceptWrites || systemSettings.autoExec;
|
|
@@ -5203,16 +5594,20 @@ Selection: ${val}`,
|
|
|
5203
5594
|
const cleanQuery = query.startsWith("/") ? query.slice(1) : query;
|
|
5204
5595
|
return COMMANDS.filter((c) => {
|
|
5205
5596
|
const cleanCmd = c.cmd.startsWith("/") ? c.cmd.slice(1) : c.cmd;
|
|
5206
|
-
return cleanCmd.includes(cleanQuery);
|
|
5597
|
+
return cleanCmd.toLowerCase().includes(cleanQuery);
|
|
5207
5598
|
});
|
|
5208
5599
|
}
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5600
|
+
let currentList = COMMANDS;
|
|
5601
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
5602
|
+
const part = parts[i].toLowerCase();
|
|
5603
|
+
const found = currentList.find((c) => c.cmd.toLowerCase() === part);
|
|
5604
|
+
if (found && found.subs) {
|
|
5605
|
+
currentList = found.subs;
|
|
5606
|
+
} else {
|
|
5607
|
+
return [];
|
|
5213
5608
|
}
|
|
5214
5609
|
}
|
|
5215
|
-
return
|
|
5610
|
+
return currentList.filter((s) => s.cmd.toLowerCase().includes(query));
|
|
5216
5611
|
}, [input]);
|
|
5217
5612
|
useEffect5(() => {
|
|
5218
5613
|
setSelectedIndex(0);
|
|
@@ -5346,19 +5741,37 @@ Selection: ${val}`,
|
|
|
5346
5741
|
setSystemSettings(newSysSettings);
|
|
5347
5742
|
newSettings.systemSettings = newSysSettings;
|
|
5348
5743
|
setMessages((prev) => [...prev, { id: Date.now(), role: "system", text: "\u{1F4C1} [EXTERNAL STORAGE] Flux Flow will use " + val.trim() + " for data after restart." }]);
|
|
5744
|
+
} else if (key === "imageSettings") {
|
|
5745
|
+
const apiKeyInput = val.trim();
|
|
5746
|
+
if (apiKeyInput.startsWith("sk_")) {
|
|
5747
|
+
const updatedSettings = { ...imageSettings, apiKey: apiKeyInput };
|
|
5748
|
+
setImageSettings(updatedSettings);
|
|
5749
|
+
newSettings.imageSettings = updatedSettings;
|
|
5750
|
+
setMessages((prev) => {
|
|
5751
|
+
setCompletedIndex(prev.length + 1);
|
|
5752
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u{1F511} [IMAGE KEY] Custom API key saved successfully.`, isMeta: true }];
|
|
5753
|
+
});
|
|
5754
|
+
} else {
|
|
5755
|
+
setImageSettings((prev) => ({ ...prev, keyType: "Default" }));
|
|
5756
|
+
newSettings.imageSettings = { ...imageSettings, keyType: "Default" };
|
|
5757
|
+
setMessages((prev) => {
|
|
5758
|
+
setCompletedIndex(prev.length + 1);
|
|
5759
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u274C [IMAGE KEY ERROR] API key must start with sk_. Key strategy reset to Default.`, isMeta: true }];
|
|
5760
|
+
});
|
|
5761
|
+
}
|
|
5349
5762
|
}
|
|
5350
5763
|
if (next) {
|
|
5351
5764
|
setInputConfig(next(key === "quotas" ? newQuotas : val));
|
|
5352
5765
|
} else {
|
|
5353
|
-
saveSettings({ ...newSettings, apiTier, quotas: newQuotas });
|
|
5766
|
+
saveSettings({ ...newSettings, apiTier, quotas: newQuotas, imageSettings: newSettings.imageSettings || imageSettings });
|
|
5354
5767
|
setInputConfig(null);
|
|
5355
|
-
setActiveView("settings");
|
|
5768
|
+
setActiveView(inputConfig?.returnView || "settings");
|
|
5356
5769
|
}
|
|
5357
5770
|
}
|
|
5358
5771
|
}
|
|
5359
5772
|
)), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
|
|
5360
5773
|
case "stats":
|
|
5361
|
-
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
|
|
5774
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (sessionImageCredits || 0).toFixed(4), " credits")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.imageCalls?.length || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.imageCalls?.reduce((sum, c) => sum + c.cost, 0) || 0).toFixed(4), " credits")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
|
|
5362
5775
|
case "autoExecDanger":
|
|
5363
5776
|
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
|
|
5364
5777
|
CommandMenu,
|
|
@@ -5724,7 +6137,7 @@ Selection: ${val}`,
|
|
|
5724
6137
|
const agentActiveMs = sessionApiTime + sessionToolTime;
|
|
5725
6138
|
const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
5726
6139
|
const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
5727
|
-
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens)))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
|
|
6140
|
+
return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (sessionImageCredits || 0).toFixed(4), " credits"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
|
|
5728
6141
|
})(), suggestions.length > 0 && (() => {
|
|
5729
6142
|
const windowSize = 5;
|
|
5730
6143
|
const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
|
|
@@ -5795,8 +6208,8 @@ var init_app = __esm({
|
|
|
5795
6208
|
init_text();
|
|
5796
6209
|
SESSION_START_TIME = Date.now();
|
|
5797
6210
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5798
|
-
packageJsonPath =
|
|
5799
|
-
packageJson = JSON.parse(
|
|
6211
|
+
packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
|
|
6212
|
+
packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
|
|
5800
6213
|
versionFluxflow = packageJson.version;
|
|
5801
6214
|
updatedOn = "2026-05-17";
|
|
5802
6215
|
ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 0 }, /* @__PURE__ */ React10.createElement(
|