fluxflow-cli 1.9.28 → 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 +720 -300
- 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')]
|
|
@@ -1027,7 +991,7 @@ ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
|
|
|
1027
991
|
Check these first; these files > training data for project consistency. Safety rules apply` : "";
|
|
1028
992
|
return `${nameStr}${nicknameStr}${userInstrStr}
|
|
1029
993
|
[SYSTEM (OVERRIDES EVERYTHING)]
|
|
1030
|
-
Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, CLI Agent. No flirting
|
|
994
|
+
Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
|
|
1031
995
|
Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented" : "Conversational & UX-focused"}
|
|
1032
996
|
CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" && mode === "Flux" ? ". PS via CMD" : ""}
|
|
1033
997
|
High Priority: [SYSTEM], [STEERING HINT]
|
|
@@ -1062,7 +1026,7 @@ ${projectContextBlock}
|
|
|
1062
1026
|
- Task Complete? End loop with [turn: finish]
|
|
1063
1027
|
[/SYSTEM]`.trim();
|
|
1064
1028
|
};
|
|
1065
|
-
getJanitorInstruction = (
|
|
1029
|
+
getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
|
|
1066
1030
|
return `
|
|
1067
1031
|
${userMemories ? `
|
|
1068
1032
|
|
|
@@ -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,
|
|
@@ -2731,14 +3018,14 @@ var init_ai = __esm({
|
|
|
2731
3018
|
isMemoryEnabled,
|
|
2732
3019
|
true
|
|
2733
3020
|
);
|
|
2734
|
-
let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0,
|
|
2735
|
-
if (agentRes.length >
|
|
3021
|
+
let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").substring(0, 24e3)}`;
|
|
3022
|
+
if (agentRes.length > 24e3) {
|
|
2736
3023
|
agentRes += "\n... (truncated) ...";
|
|
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 = "";
|
|
@@ -2836,6 +3123,10 @@ DEBUG [${date}]: ${finalSynthesis}
|
|
|
2836
3123
|
} catch (janitorErr) {
|
|
2837
3124
|
attempts++;
|
|
2838
3125
|
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
3126
|
+
if (process.stdout.isTTY) {
|
|
3127
|
+
process.stdout.write(`\x1B]0;Memory Error\x07`);
|
|
3128
|
+
}
|
|
3129
|
+
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
2839
3130
|
const janitorErrDir = path15.join(LOGS_DIR, "janitor");
|
|
2840
3131
|
if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
|
|
2841
3132
|
fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
|
|
@@ -3269,7 +3560,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3269
3560
|
"SearchKeyword": "search_keyword",
|
|
3270
3561
|
"Memory": "memory",
|
|
3271
3562
|
"Chat": "chat",
|
|
3272
|
-
"chat": "chat"
|
|
3563
|
+
"chat": "chat",
|
|
3564
|
+
"GenerateImage": "generate_image",
|
|
3565
|
+
"generate_image": "generate_image"
|
|
3273
3566
|
};
|
|
3274
3567
|
const potentialTool = NORMALIZE_MAP[rawToolName] || rawToolName;
|
|
3275
3568
|
const partialArgs = toolContext.args || "";
|
|
@@ -3309,7 +3602,8 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3309
3602
|
"search_keyword": "Searching Keywords",
|
|
3310
3603
|
"exec_command": "Running Command",
|
|
3311
3604
|
"ask": "Asking User",
|
|
3312
|
-
"memory": "Updating Memory"
|
|
3605
|
+
"memory": "Updating Memory",
|
|
3606
|
+
"generate_image": "Generating Image"
|
|
3313
3607
|
};
|
|
3314
3608
|
const toolTitle = TOOL_TITLES[potentialTool] || "Working";
|
|
3315
3609
|
process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
|
|
@@ -3329,7 +3623,10 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3329
3623
|
"low": 200,
|
|
3330
3624
|
"medium": 500,
|
|
3331
3625
|
"high": 2e3,
|
|
3332
|
-
"max": 3500
|
|
3626
|
+
"max": 3500,
|
|
3627
|
+
"xhigh": 3500,
|
|
3628
|
+
"off": 50,
|
|
3629
|
+
"fast": 50
|
|
3333
3630
|
};
|
|
3334
3631
|
const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
|
|
3335
3632
|
let isOverVerboseThinking = wordCount > cap;
|
|
@@ -3387,7 +3684,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3387
3684
|
"SearchKeyword": "search_keyword",
|
|
3388
3685
|
"Memory": "memory",
|
|
3389
3686
|
"Chat": "chat",
|
|
3390
|
-
"chat": "chat"
|
|
3687
|
+
"chat": "chat",
|
|
3688
|
+
"GenerateImage": "generate_image",
|
|
3689
|
+
"generate_image": "generate_image"
|
|
3391
3690
|
};
|
|
3392
3691
|
const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
|
|
3393
3692
|
const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
|
|
@@ -3441,6 +3740,9 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3441
3740
|
} else if (normToolName === "search_keyword") {
|
|
3442
3741
|
const { keyword } = parseArgs(toolCall.args);
|
|
3443
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();
|
|
3444
3746
|
} else if (normToolName === "exec_command" || normToolName === "ask") {
|
|
3445
3747
|
label = "";
|
|
3446
3748
|
} else {
|
|
@@ -3502,7 +3804,7 @@ ${boxBottom}` };
|
|
|
3502
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**" : ""}` });
|
|
3503
3805
|
yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
|
|
3504
3806
|
await incrementUsage("toolDenied");
|
|
3505
|
-
if (settings.onToolResult) settings.onToolResult("denied");
|
|
3807
|
+
if (settings.onToolResult) settings.onToolResult("denied", normToolName);
|
|
3506
3808
|
toolCallPointer++;
|
|
3507
3809
|
continue;
|
|
3508
3810
|
}
|
|
@@ -3536,11 +3838,11 @@ ${boxBottom}` };
|
|
|
3536
3838
|
const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
|
|
3537
3839
|
if (isSuccess) {
|
|
3538
3840
|
await incrementUsage("toolSuccess");
|
|
3539
|
-
if (settings.onToolResult) settings.onToolResult("success");
|
|
3841
|
+
if (settings.onToolResult) settings.onToolResult("success", normToolName);
|
|
3540
3842
|
} else if (isDenied) {
|
|
3541
3843
|
} else {
|
|
3542
3844
|
await incrementUsage("toolFailure");
|
|
3543
|
-
if (settings.onToolResult) settings.onToolResult("failure");
|
|
3845
|
+
if (settings.onToolResult) settings.onToolResult("failure", normToolName);
|
|
3544
3846
|
}
|
|
3545
3847
|
const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
|
|
3546
3848
|
toolResults.push({ role: "user", text: aiContent, binaryPart });
|
|
@@ -3685,97 +3987,6 @@ ${timestamp}`;
|
|
|
3685
3987
|
}
|
|
3686
3988
|
});
|
|
3687
3989
|
|
|
3688
|
-
// src/utils/settings.js
|
|
3689
|
-
import fs17 from "fs-extra";
|
|
3690
|
-
import path16 from "path";
|
|
3691
|
-
var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
|
|
3692
|
-
var init_settings = __esm({
|
|
3693
|
-
"src/utils/settings.js"() {
|
|
3694
|
-
init_paths();
|
|
3695
|
-
DEFAULT_SETTINGS = {
|
|
3696
|
-
mode: "Flux",
|
|
3697
|
-
thinkingLevel: "Medium",
|
|
3698
|
-
activeModel: "gemma-4-31b-it",
|
|
3699
|
-
showFullThinking: true,
|
|
3700
|
-
apiTier: "Free",
|
|
3701
|
-
quotas: {
|
|
3702
|
-
agentLimit: 1500,
|
|
3703
|
-
backgroundLimit: 1500,
|
|
3704
|
-
searchLimit: 100,
|
|
3705
|
-
customModelId: "",
|
|
3706
|
-
customLimit: 0
|
|
3707
|
-
},
|
|
3708
|
-
systemSettings: {
|
|
3709
|
-
memory: true,
|
|
3710
|
-
compression: 0,
|
|
3711
|
-
autoExec: false,
|
|
3712
|
-
allowExternalAccess: false,
|
|
3713
|
-
autoDeleteHistory: "7d",
|
|
3714
|
-
useExternalData: false,
|
|
3715
|
-
externalDataPath: ""
|
|
3716
|
-
},
|
|
3717
|
-
profileData: {
|
|
3718
|
-
name: null,
|
|
3719
|
-
nickname: null,
|
|
3720
|
-
instructions: null
|
|
3721
|
-
}
|
|
3722
|
-
};
|
|
3723
|
-
loadSettings = async () => {
|
|
3724
|
-
try {
|
|
3725
|
-
if (await fs17.exists(SETTINGS_FILE)) {
|
|
3726
|
-
const saved = await fs17.readJson(SETTINGS_FILE);
|
|
3727
|
-
const merged = {
|
|
3728
|
-
...DEFAULT_SETTINGS,
|
|
3729
|
-
...saved,
|
|
3730
|
-
quotas: { ...DEFAULT_SETTINGS.quotas, ...saved.quotas },
|
|
3731
|
-
systemSettings: { ...DEFAULT_SETTINGS.systemSettings, ...saved.systemSettings },
|
|
3732
|
-
profileData: { ...DEFAULT_SETTINGS.profileData, ...saved.profileData }
|
|
3733
|
-
};
|
|
3734
|
-
if (merged.showFullThinking === false) {
|
|
3735
|
-
merged.showFullThinking = true;
|
|
3736
|
-
await fs17.writeJson(SETTINGS_FILE, merged, { spaces: 2 });
|
|
3737
|
-
}
|
|
3738
|
-
return merged;
|
|
3739
|
-
}
|
|
3740
|
-
} catch (err) {
|
|
3741
|
-
console.error("Failed to load settings:", err);
|
|
3742
|
-
}
|
|
3743
|
-
return DEFAULT_SETTINGS;
|
|
3744
|
-
};
|
|
3745
|
-
migrateToExternal = async (newPath) => {
|
|
3746
|
-
const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
3747
|
-
const folders = ["logs", "secret"];
|
|
3748
|
-
for (const folder of folders) {
|
|
3749
|
-
const src = path16.join(FLUXFLOW_DIR2, folder);
|
|
3750
|
-
const dest = path16.join(newPath, folder);
|
|
3751
|
-
try {
|
|
3752
|
-
if (await fs17.exists(src)) {
|
|
3753
|
-
await fs17.ensureDir(dest);
|
|
3754
|
-
await fs17.copy(src, dest, { overwrite: true });
|
|
3755
|
-
}
|
|
3756
|
-
} catch (err) {
|
|
3757
|
-
console.error(`Migration failed for ${folder}:`, err);
|
|
3758
|
-
}
|
|
3759
|
-
}
|
|
3760
|
-
};
|
|
3761
|
-
saveSettings = async (settings) => {
|
|
3762
|
-
try {
|
|
3763
|
-
const current = await loadSettings();
|
|
3764
|
-
if (!current.systemSettings.useExternalData && settings.systemSettings?.useExternalData && settings.systemSettings?.externalDataPath) {
|
|
3765
|
-
await migrateToExternal(settings.systemSettings.externalDataPath);
|
|
3766
|
-
}
|
|
3767
|
-
const updated = { ...current, ...settings };
|
|
3768
|
-
await fs17.ensureDir(path16.dirname(SETTINGS_FILE));
|
|
3769
|
-
await fs17.writeJson(SETTINGS_FILE, updated, { spaces: 2 });
|
|
3770
|
-
return true;
|
|
3771
|
-
} catch (err) {
|
|
3772
|
-
console.error("Failed to save settings:", err);
|
|
3773
|
-
return false;
|
|
3774
|
-
}
|
|
3775
|
-
};
|
|
3776
|
-
}
|
|
3777
|
-
});
|
|
3778
|
-
|
|
3779
3990
|
// src/components/ResumeModal.jsx
|
|
3780
3991
|
import React7, { useState as useState4, useEffect as useEffect2 } from "react";
|
|
3781
3992
|
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
@@ -3979,7 +4190,7 @@ var init_UpdateProcessor = __esm({
|
|
|
3979
4190
|
import puppeteer4 from "puppeteer";
|
|
3980
4191
|
import { exec as exec3 } from "child_process";
|
|
3981
4192
|
import { promisify } from "util";
|
|
3982
|
-
import
|
|
4193
|
+
import fs17 from "fs";
|
|
3983
4194
|
var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
|
|
3984
4195
|
var init_setup = __esm({
|
|
3985
4196
|
"src/utils/setup.js"() {
|
|
@@ -3987,7 +4198,7 @@ var init_setup = __esm({
|
|
|
3987
4198
|
checkPuppeteerReady = () => {
|
|
3988
4199
|
try {
|
|
3989
4200
|
const exePath = puppeteer4.executablePath();
|
|
3990
|
-
const exists = exePath &&
|
|
4201
|
+
const exists = exePath && fs17.existsSync(exePath);
|
|
3991
4202
|
if (exists) return true;
|
|
3992
4203
|
} catch (e) {
|
|
3993
4204
|
return false;
|
|
@@ -4021,8 +4232,8 @@ import os3 from "os";
|
|
|
4021
4232
|
import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
|
|
4022
4233
|
import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
|
|
4023
4234
|
import Spinner2 from "ink-spinner";
|
|
4024
|
-
import
|
|
4025
|
-
import
|
|
4235
|
+
import fs18 from "fs-extra";
|
|
4236
|
+
import path16 from "path";
|
|
4026
4237
|
import { exec as exec4 } from "child_process";
|
|
4027
4238
|
import { fileURLToPath } from "url";
|
|
4028
4239
|
import { MultilineInput } from "ink-multiline-input";
|
|
@@ -4118,6 +4329,7 @@ function App() {
|
|
|
4118
4329
|
const [inputConfig, setInputConfig] = useState7(null);
|
|
4119
4330
|
const [systemSettings, setSystemSettings] = useState7({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
|
|
4120
4331
|
const [profileData, setProfileData] = useState7({ name: null, nickname: null, instructions: null });
|
|
4332
|
+
const [imageSettings, setImageSettings] = useState7({ keyType: "Default", quality: "Low-High", apiKey: "" });
|
|
4121
4333
|
const [sessionStats, setSessionStats] = useState7({ tokens: 0 });
|
|
4122
4334
|
const [sessionAgentCalls, setSessionAgentCalls] = useState7(0);
|
|
4123
4335
|
const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState7(0);
|
|
@@ -4127,6 +4339,8 @@ function App() {
|
|
|
4127
4339
|
const [sessionToolDenied, setSessionToolDenied] = useState7(0);
|
|
4128
4340
|
const [sessionApiTime, setSessionApiTime] = useState7(0);
|
|
4129
4341
|
const [sessionToolTime, setSessionToolTime] = useState7(0);
|
|
4342
|
+
const [sessionImageCount, setSessionImageCount] = useState7(0);
|
|
4343
|
+
const [sessionImageCredits, setSessionImageCredits] = useState7(0);
|
|
4130
4344
|
const [dailyUsage, setDailyUsage] = useState7(null);
|
|
4131
4345
|
const [chatId, setChatId] = useState7(generateChatId());
|
|
4132
4346
|
const [activeCommand, setActiveCommand] = useState7(null);
|
|
@@ -4376,6 +4590,7 @@ function App() {
|
|
|
4376
4590
|
};
|
|
4377
4591
|
setSystemSettings(freshSettings);
|
|
4378
4592
|
setProfileData(saved.profileData);
|
|
4593
|
+
setImageSettings(saved.imageSettings || { keyType: "Default", quality: "Low-High", apiKey: "" });
|
|
4379
4594
|
const key = await getAPIKey();
|
|
4380
4595
|
if (key) {
|
|
4381
4596
|
setApiKey(key);
|
|
@@ -4416,10 +4631,11 @@ function App() {
|
|
|
4416
4631
|
activeModel,
|
|
4417
4632
|
showFullThinking,
|
|
4418
4633
|
systemSettings,
|
|
4419
|
-
profileData
|
|
4634
|
+
profileData,
|
|
4635
|
+
imageSettings
|
|
4420
4636
|
});
|
|
4421
4637
|
}
|
|
4422
|
-
}, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, isInitializing]);
|
|
4638
|
+
}, [mode, thinkingLevel, activeModel, showFullThinking, systemSettings, profileData, imageSettings, isInitializing]);
|
|
4423
4639
|
const handleSetup = async (val) => {
|
|
4424
4640
|
const key = val.trim();
|
|
4425
4641
|
if (key.length >= 30) {
|
|
@@ -4471,6 +4687,40 @@ function App() {
|
|
|
4471
4687
|
{ cmd: "/resume", desc: "Load previous session" },
|
|
4472
4688
|
{ cmd: "/save", desc: "Force save current chat" },
|
|
4473
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
|
+
},
|
|
4474
4724
|
{
|
|
4475
4725
|
cmd: "/mode",
|
|
4476
4726
|
desc: "Toggle Flux/Flow modes",
|
|
@@ -4524,14 +4774,15 @@ function App() {
|
|
|
4524
4774
|
]
|
|
4525
4775
|
}
|
|
4526
4776
|
];
|
|
4527
|
-
const handleSubmit = (value) => {
|
|
4777
|
+
const handleSubmit = async (value) => {
|
|
4528
4778
|
if (suggestions.length > 0) {
|
|
4529
4779
|
const nextMatch = suggestions[selectedIndex] || suggestions[0];
|
|
4530
4780
|
const parts = value.split(" ");
|
|
4531
4781
|
if (parts.length === 1) {
|
|
4532
4782
|
setInput(nextMatch.cmd + " ");
|
|
4533
4783
|
} else {
|
|
4534
|
-
|
|
4784
|
+
const parentParts = parts.slice(0, -1);
|
|
4785
|
+
setInput(parentParts.join(" ") + " " + nextMatch.cmd + " ");
|
|
4535
4786
|
}
|
|
4536
4787
|
setSelectedIndex(0);
|
|
4537
4788
|
return;
|
|
@@ -4630,6 +4881,135 @@ ${hintText}`, color: "magenta" }];
|
|
|
4630
4881
|
}
|
|
4631
4882
|
break;
|
|
4632
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
|
+
}
|
|
4633
5013
|
case "/thinking": {
|
|
4634
5014
|
let formattedLevel;
|
|
4635
5015
|
if (parts[1]) {
|
|
@@ -4737,12 +5117,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4737
5117
|
setCompletedIndex(prev.length + 1);
|
|
4738
5118
|
return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset...", isMeta: true }];
|
|
4739
5119
|
});
|
|
4740
|
-
if (
|
|
4741
|
-
if (
|
|
4742
|
-
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);
|
|
4743
5123
|
try {
|
|
4744
|
-
const items =
|
|
4745
|
-
if (items.length === 0)
|
|
5124
|
+
const items = fs18.readdirSync(FLUXFLOW_DIR);
|
|
5125
|
+
if (items.length === 0) fs18.removeSync(FLUXFLOW_DIR);
|
|
4746
5126
|
} catch (e) {
|
|
4747
5127
|
}
|
|
4748
5128
|
setTimeout(() => {
|
|
@@ -4799,14 +5179,14 @@ ${list || "No saved chats found."}`, isMeta: true }];
|
|
|
4799
5179
|
# SKILLS & WORKFLOWS
|
|
4800
5180
|
- [Define custom step-by-step recipes for this project here]
|
|
4801
5181
|
`;
|
|
4802
|
-
const filePath =
|
|
4803
|
-
if (
|
|
5182
|
+
const filePath = path16.join(process.cwd(), "FluxFlow.md");
|
|
5183
|
+
if (fs18.pathExistsSync(filePath)) {
|
|
4804
5184
|
setMessages((prev) => {
|
|
4805
5185
|
setCompletedIndex(prev.length + 1);
|
|
4806
5186
|
return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
|
|
4807
5187
|
});
|
|
4808
5188
|
} else {
|
|
4809
|
-
|
|
5189
|
+
fs18.writeFileSync(filePath, template);
|
|
4810
5190
|
setMessages((prev) => {
|
|
4811
5191
|
setCompletedIndex(prev.length + 1);
|
|
4812
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 }];
|
|
@@ -4894,10 +5274,28 @@ OUTPUT: ${execOutputRef.current}`;
|
|
|
4894
5274
|
setIsTerminalFocused(false);
|
|
4895
5275
|
setExecOutput("");
|
|
4896
5276
|
},
|
|
4897
|
-
onToolResult: (status) => {
|
|
4898
|
-
if (status === "success")
|
|
4899
|
-
|
|
4900
|
-
|
|
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
|
+
}
|
|
4901
5299
|
},
|
|
4902
5300
|
onToolApproval: async (tool, args) => {
|
|
4903
5301
|
const isAuto = autoAcceptWrites || systemSettings.autoExec;
|
|
@@ -5196,16 +5594,20 @@ Selection: ${val}`,
|
|
|
5196
5594
|
const cleanQuery = query.startsWith("/") ? query.slice(1) : query;
|
|
5197
5595
|
return COMMANDS.filter((c) => {
|
|
5198
5596
|
const cleanCmd = c.cmd.startsWith("/") ? c.cmd.slice(1) : c.cmd;
|
|
5199
|
-
return cleanCmd.includes(cleanQuery);
|
|
5597
|
+
return cleanCmd.toLowerCase().includes(cleanQuery);
|
|
5200
5598
|
});
|
|
5201
5599
|
}
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
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 [];
|
|
5206
5608
|
}
|
|
5207
5609
|
}
|
|
5208
|
-
return
|
|
5610
|
+
return currentList.filter((s) => s.cmd.toLowerCase().includes(query));
|
|
5209
5611
|
}, [input]);
|
|
5210
5612
|
useEffect5(() => {
|
|
5211
5613
|
setSelectedIndex(0);
|
|
@@ -5339,19 +5741,37 @@ Selection: ${val}`,
|
|
|
5339
5741
|
setSystemSettings(newSysSettings);
|
|
5340
5742
|
newSettings.systemSettings = newSysSettings;
|
|
5341
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
|
+
}
|
|
5342
5762
|
}
|
|
5343
5763
|
if (next) {
|
|
5344
5764
|
setInputConfig(next(key === "quotas" ? newQuotas : val));
|
|
5345
5765
|
} else {
|
|
5346
|
-
saveSettings({ ...newSettings, apiTier, quotas: newQuotas });
|
|
5766
|
+
saveSettings({ ...newSettings, apiTier, quotas: newQuotas, imageSettings: newSettings.imageSettings || imageSettings });
|
|
5347
5767
|
setInputConfig(null);
|
|
5348
|
-
setActiveView("settings");
|
|
5768
|
+
setActiveView(inputConfig?.returnView || "settings");
|
|
5349
5769
|
}
|
|
5350
5770
|
}
|
|
5351
5771
|
}
|
|
5352
5772
|
)), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
|
|
5353
5773
|
case "stats":
|
|
5354
|
-
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)"));
|
|
5355
5775
|
case "autoExecDanger":
|
|
5356
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(
|
|
5357
5777
|
CommandMenu,
|
|
@@ -5717,7 +6137,7 @@ Selection: ${val}`,
|
|
|
5717
6137
|
const agentActiveMs = sessionApiTime + sessionToolTime;
|
|
5718
6138
|
const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
5719
6139
|
const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
|
|
5720
|
-
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, "%)"))));
|
|
5721
6141
|
})(), suggestions.length > 0 && (() => {
|
|
5722
6142
|
const windowSize = 5;
|
|
5723
6143
|
const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
|
|
@@ -5788,8 +6208,8 @@ var init_app = __esm({
|
|
|
5788
6208
|
init_text();
|
|
5789
6209
|
SESSION_START_TIME = Date.now();
|
|
5790
6210
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5791
|
-
packageJsonPath =
|
|
5792
|
-
packageJson = JSON.parse(
|
|
6211
|
+
packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
|
|
6212
|
+
packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
|
|
5793
6213
|
versionFluxflow = packageJson.version;
|
|
5794
6214
|
updatedOn = "2026-05-17";
|
|
5795
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(
|