fluxflow-cli 1.11.2 → 1.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluxflow.js +117 -25
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -173,7 +173,7 @@ var init_ChatLayout = __esm({
|
|
|
173
173
|
};
|
|
174
174
|
cleanSignals = (text) => {
|
|
175
175
|
if (!text) return text;
|
|
176
|
-
let result = text;
|
|
176
|
+
let result = text.replace(/<\/think>(\r?\n){2}/gi, "</think>").replace(/(\r?\n){2}(?=\[?(?:tool:functions|tool\.functions|\s*turn\s*:))/gi, "");
|
|
177
177
|
const trigger = "tool:functions.";
|
|
178
178
|
while (true) {
|
|
179
179
|
const lowerResult = result.toLowerCase();
|
|
@@ -1368,11 +1368,25 @@ var init_history = __esm({
|
|
|
1368
1368
|
// src/utils/usage.js
|
|
1369
1369
|
import fs6 from "fs-extra";
|
|
1370
1370
|
import path5 from "path";
|
|
1371
|
-
|
|
1371
|
+
import os3 from "os";
|
|
1372
|
+
var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
1372
1373
|
var init_usage = __esm({
|
|
1373
1374
|
"src/utils/usage.js"() {
|
|
1374
1375
|
init_paths();
|
|
1375
1376
|
init_crypto();
|
|
1377
|
+
getLocalBackupPath = () => {
|
|
1378
|
+
if (process.platform === "win32") {
|
|
1379
|
+
const localAppData = process.env.LOCALAPPDATA || path5.join(os3.homedir(), "AppData", "Local");
|
|
1380
|
+
return path5.join(localAppData, "FxFl", "backups", "backup.json");
|
|
1381
|
+
}
|
|
1382
|
+
if (process.platform === "darwin") {
|
|
1383
|
+
return path5.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
|
|
1384
|
+
}
|
|
1385
|
+
const xdgDataHome = process.env.XDG_DATA_HOME || path5.join(os3.homedir(), ".local", "share");
|
|
1386
|
+
return path5.join(xdgDataHome, "fxfl", "backups", "backup.json");
|
|
1387
|
+
};
|
|
1388
|
+
BACKUP_FILE = getLocalBackupPath();
|
|
1389
|
+
generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
1376
1390
|
cachedUsage = null;
|
|
1377
1391
|
writeTimeout = null;
|
|
1378
1392
|
lastWriteTime = 0;
|
|
@@ -1390,28 +1404,67 @@ var init_usage = __esm({
|
|
|
1390
1404
|
};
|
|
1391
1405
|
loadUsageFromFile = async () => {
|
|
1392
1406
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
1407
|
+
let primaryData = null;
|
|
1408
|
+
let backupData = null;
|
|
1393
1409
|
try {
|
|
1394
1410
|
if (await fs6.exists(USAGE_FILE)) {
|
|
1395
1411
|
const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
|
|
1396
|
-
let data;
|
|
1397
1412
|
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
1398
|
-
|
|
1413
|
+
primaryData = JSON.parse(rawContent);
|
|
1399
1414
|
} else {
|
|
1400
|
-
|
|
1415
|
+
primaryData = JSON.parse(decryptAes(rawContent));
|
|
1401
1416
|
}
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1417
|
+
}
|
|
1418
|
+
} catch (err) {
|
|
1419
|
+
}
|
|
1420
|
+
try {
|
|
1421
|
+
if (await fs6.exists(BACKUP_FILE)) {
|
|
1422
|
+
const rawContent = (await fs6.readFile(BACKUP_FILE, "utf8")).trim();
|
|
1423
|
+
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
1424
|
+
backupData = JSON.parse(rawContent);
|
|
1425
|
+
} else {
|
|
1426
|
+
backupData = JSON.parse(decryptAes(rawContent));
|
|
1411
1427
|
}
|
|
1412
1428
|
}
|
|
1413
1429
|
} catch (err) {
|
|
1414
1430
|
}
|
|
1431
|
+
let resolvedData = null;
|
|
1432
|
+
if (primaryData && backupData) {
|
|
1433
|
+
if (primaryData.saveId !== backupData.saveId) {
|
|
1434
|
+
resolvedData = primaryData;
|
|
1435
|
+
try {
|
|
1436
|
+
await fs6.ensureDir(path5.dirname(BACKUP_FILE));
|
|
1437
|
+
await fs6.copy(USAGE_FILE, BACKUP_FILE);
|
|
1438
|
+
} catch (e) {
|
|
1439
|
+
}
|
|
1440
|
+
} else {
|
|
1441
|
+
resolvedData = primaryData;
|
|
1442
|
+
}
|
|
1443
|
+
} else if (primaryData && !backupData) {
|
|
1444
|
+
resolvedData = primaryData;
|
|
1445
|
+
try {
|
|
1446
|
+
await fs6.ensureDir(path5.dirname(BACKUP_FILE));
|
|
1447
|
+
await fs6.copy(USAGE_FILE, BACKUP_FILE);
|
|
1448
|
+
} catch (e) {
|
|
1449
|
+
}
|
|
1450
|
+
} else if (!primaryData && backupData) {
|
|
1451
|
+
resolvedData = backupData;
|
|
1452
|
+
try {
|
|
1453
|
+
await fs6.ensureDir(path5.dirname(USAGE_FILE));
|
|
1454
|
+
await fs6.copy(BACKUP_FILE, USAGE_FILE);
|
|
1455
|
+
} catch (e) {
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
if (resolvedData && resolvedData.date === today && resolvedData.stats) {
|
|
1459
|
+
const mergedStats = { ...defaultStats, ...resolvedData.stats };
|
|
1460
|
+
if (!Array.isArray(mergedStats.imageCalls)) {
|
|
1461
|
+
mergedStats.imageCalls = [];
|
|
1462
|
+
}
|
|
1463
|
+
return {
|
|
1464
|
+
...resolvedData,
|
|
1465
|
+
stats: mergedStats
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1415
1468
|
return { date: today, stats: { ...defaultStats } };
|
|
1416
1469
|
};
|
|
1417
1470
|
flushUsage = async () => {
|
|
@@ -1449,6 +1502,7 @@ var init_usage = __esm({
|
|
|
1449
1502
|
}
|
|
1450
1503
|
}
|
|
1451
1504
|
}
|
|
1505
|
+
cachedUsage.saveId = generateSaveId();
|
|
1452
1506
|
const tempFile = USAGE_FILE + ".tmp";
|
|
1453
1507
|
const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
|
|
1454
1508
|
await fs6.writeFile(tempFile, encryptedStr, "utf8");
|
|
@@ -1456,6 +1510,11 @@ var init_usage = __esm({
|
|
|
1456
1510
|
await fs6.fsync(fd);
|
|
1457
1511
|
await fs6.close(fd);
|
|
1458
1512
|
await fs6.rename(tempFile, USAGE_FILE);
|
|
1513
|
+
try {
|
|
1514
|
+
await fs6.ensureDir(path5.dirname(BACKUP_FILE));
|
|
1515
|
+
await fs6.copy(USAGE_FILE, BACKUP_FILE);
|
|
1516
|
+
} catch (backupErr) {
|
|
1517
|
+
}
|
|
1459
1518
|
isDirty = false;
|
|
1460
1519
|
lastWriteTime = Date.now();
|
|
1461
1520
|
} catch (e) {
|
|
@@ -2790,6 +2849,26 @@ var init_write_pdf = __esm({
|
|
|
2790
2849
|
]
|
|
2791
2850
|
});
|
|
2792
2851
|
const page = await browser.newPage();
|
|
2852
|
+
let resolvedContent = content;
|
|
2853
|
+
const imgRegex = /<img[^>]+src=["']([^"']+)["']/gi;
|
|
2854
|
+
let match;
|
|
2855
|
+
while ((match = imgRegex.exec(content)) !== null) {
|
|
2856
|
+
const originalSrc = match[1];
|
|
2857
|
+
if (!originalSrc || originalSrc.startsWith("http://") || originalSrc.startsWith("https://") || originalSrc.startsWith("data:")) {
|
|
2858
|
+
continue;
|
|
2859
|
+
}
|
|
2860
|
+
try {
|
|
2861
|
+
const imgPath = path11.resolve(process.cwd(), originalSrc);
|
|
2862
|
+
if (await fs12.pathExists(imgPath)) {
|
|
2863
|
+
const ext = path11.extname(imgPath).toLowerCase().replace(".", "") || "png";
|
|
2864
|
+
const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
|
|
2865
|
+
const base64 = await fs12.readFile(imgPath, "base64");
|
|
2866
|
+
const dataUri = `data:image/${mime};base64,${base64}`;
|
|
2867
|
+
resolvedContent = resolvedContent.split(originalSrc).join(dataUri);
|
|
2868
|
+
}
|
|
2869
|
+
} catch (e) {
|
|
2870
|
+
}
|
|
2871
|
+
}
|
|
2793
2872
|
const styledContent = `
|
|
2794
2873
|
<style>
|
|
2795
2874
|
@page {
|
|
@@ -2819,7 +2898,7 @@ var init_write_pdf = __esm({
|
|
|
2819
2898
|
}
|
|
2820
2899
|
</style>
|
|
2821
2900
|
<div class="watermark">Generated by FluxFlow CLI (AI)</div>
|
|
2822
|
-
${
|
|
2901
|
+
${resolvedContent}
|
|
2823
2902
|
`;
|
|
2824
2903
|
await page.setContent(styledContent, { waitUntil: "networkidle0", timeout: 18e4 });
|
|
2825
2904
|
const pdfBytes = await page.pdf({
|
|
@@ -3795,6 +3874,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3795
3874
|
let lastToolSniffed = null;
|
|
3796
3875
|
let lastToolDetail = null;
|
|
3797
3876
|
let lastToolEventTime = null;
|
|
3877
|
+
let lastToolFinishedAt = 0;
|
|
3798
3878
|
let toolResults = [];
|
|
3799
3879
|
let toolCallPointer = 0;
|
|
3800
3880
|
let isThinkingLoop = false;
|
|
@@ -4223,6 +4303,12 @@ ${boxBottom}` };
|
|
|
4223
4303
|
}
|
|
4224
4304
|
}
|
|
4225
4305
|
}
|
|
4306
|
+
if (lastToolFinishedAt > 0) {
|
|
4307
|
+
const timeSinceLastTool = Date.now() - lastToolFinishedAt;
|
|
4308
|
+
if (timeSinceLastTool < 1e3) {
|
|
4309
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3 - timeSinceLastTool));
|
|
4310
|
+
}
|
|
4311
|
+
}
|
|
4226
4312
|
const effectiveStart = lastToolEventTime || Date.now();
|
|
4227
4313
|
yield { type: "spinner", content: false };
|
|
4228
4314
|
let result = await dispatchTool(normToolName, toolCall.args, {
|
|
@@ -4236,6 +4322,7 @@ ${boxBottom}` };
|
|
|
4236
4322
|
process.stdout.write(`\x1B]0;Working...\x07`);
|
|
4237
4323
|
}
|
|
4238
4324
|
const toolEnd = Date.now();
|
|
4325
|
+
lastToolFinishedAt = toolEnd;
|
|
4239
4326
|
yield { type: "tool_time", content: toolEnd - effectiveStart };
|
|
4240
4327
|
lastToolEventTime = toolEnd;
|
|
4241
4328
|
let binaryPart = null;
|
|
@@ -4693,7 +4780,7 @@ var app_exports = {};
|
|
|
4693
4780
|
__export(app_exports, {
|
|
4694
4781
|
default: () => App
|
|
4695
4782
|
});
|
|
4696
|
-
import
|
|
4783
|
+
import os4 from "os";
|
|
4697
4784
|
import React10, { useState as useState7, useEffect as useEffect5, useRef as useRef2, useMemo } from "react";
|
|
4698
4785
|
import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
|
|
4699
4786
|
import Spinner2 from "ink-spinner";
|
|
@@ -4868,7 +4955,7 @@ function App() {
|
|
|
4868
4955
|
const [messages, setMessages] = useState7(() => {
|
|
4869
4956
|
const logoMsg = { id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true };
|
|
4870
4957
|
const welcomeMsg = { id: "welcome", role: "system", text: "\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true };
|
|
4871
|
-
const isHomeDir = process.cwd() ===
|
|
4958
|
+
const isHomeDir = process.cwd() === os4.homedir();
|
|
4872
4959
|
const isSystemDir = (() => {
|
|
4873
4960
|
const cwd = process.cwd().toLowerCase();
|
|
4874
4961
|
if (process.platform === "win32") {
|
|
@@ -4896,7 +4983,7 @@ function App() {
|
|
|
4896
4983
|
id: "home-warning",
|
|
4897
4984
|
role: "system",
|
|
4898
4985
|
text: `[SECURITY ALERT] HOME DIRECTORY DETECTED`,
|
|
4899
|
-
subText: `You are currently in ${
|
|
4986
|
+
subText: `You are currently in ${os4.homedir()}. Working here is high-risk as the agent may modify system-sensitive configurations. Please move to a project folder for safety.`,
|
|
4900
4987
|
isHomeWarning: true,
|
|
4901
4988
|
isMeta: true
|
|
4902
4989
|
});
|
|
@@ -5305,7 +5392,8 @@ ${hintText}`, color: "magenta" }];
|
|
|
5305
5392
|
const resumedMsgs = [...target.messages];
|
|
5306
5393
|
const hasLogo = resumedMsgs[0]?.text?.includes("\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557");
|
|
5307
5394
|
if (!hasLogo) {
|
|
5308
|
-
resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text:
|
|
5395
|
+
resumedMsgs.unshift({ id: "welcome-" + Date.now(), role: "system", text: "\u{1F30A}\u26A1 Resuming Flux Flow Session...", isMeta: true });
|
|
5396
|
+
resumedMsgs.unshift({ id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true });
|
|
5309
5397
|
}
|
|
5310
5398
|
setMessages(resumedMsgs);
|
|
5311
5399
|
setMessages((prev) => [...prev, { id: "sys-" + Date.now(), role: "system", text: `\u{1F4E1} SESSION RESUMED: [${targetId}]`, isMeta: true }]);
|
|
@@ -5321,8 +5409,11 @@ ${hintText}`, color: "magenta" }];
|
|
|
5321
5409
|
break;
|
|
5322
5410
|
}
|
|
5323
5411
|
case "/clear": {
|
|
5324
|
-
setMessages([
|
|
5325
|
-
|
|
5412
|
+
setMessages([
|
|
5413
|
+
{ id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true },
|
|
5414
|
+
{ id: "welcome-" + Date.now(), role: "system", text: "\u{1F30A}\u26A1 Welcome back to Flux Flow! Context cleared.", isMeta: true }
|
|
5415
|
+
]);
|
|
5416
|
+
setCompletedIndex(2);
|
|
5326
5417
|
setChatId(generateChatId());
|
|
5327
5418
|
setSessionStats({ tokens: 0 });
|
|
5328
5419
|
setIsExpanded(false);
|
|
@@ -5481,21 +5572,22 @@ ${hintText}`, color: "magenta" }];
|
|
|
5481
5572
|
let formattedLevel;
|
|
5482
5573
|
if (parts[1]) {
|
|
5483
5574
|
let val = parts[1].toLowerCase();
|
|
5575
|
+
const isBypass = parts.includes("--bypass");
|
|
5484
5576
|
formattedLevel = val.charAt(0).toUpperCase() + val.slice(1);
|
|
5485
5577
|
if (val === "xhigh") {
|
|
5486
5578
|
formattedLevel = "xHigh";
|
|
5487
5579
|
}
|
|
5488
|
-
if (mode === "Flow" && (formattedLevel === "Medium" || formattedLevel === "High" || formattedLevel === "xHigh")) {
|
|
5580
|
+
if (!isBypass && mode === "Flow" && (formattedLevel === "Medium" || formattedLevel === "High" || formattedLevel === "xHigh")) {
|
|
5489
5581
|
setMessages((prev) => {
|
|
5490
5582
|
setCompletedIndex(prev.length + 1);
|
|
5491
5583
|
return [...prev, { id: Date.now(), role: "system", text: `\u274C [RESTRICTED] "${formattedLevel}" is restricted in Flow mode. Switch to Flux to enable Higher Thinking Levels.`, isMeta: true }];
|
|
5492
5584
|
});
|
|
5493
5585
|
} else {
|
|
5494
5586
|
setThinkingLevel(formattedLevel);
|
|
5495
|
-
const s2 = emojiSpace(
|
|
5587
|
+
const s2 = emojiSpace(1);
|
|
5496
5588
|
setMessages((prev) => {
|
|
5497
5589
|
setCompletedIndex(prev.length + 1);
|
|
5498
|
-
return [...prev, { id: Date.now(), role: "system", text: `\u{1F527}
|
|
5590
|
+
return [...prev, { id: Date.now(), role: "system", text: `\u{1F527} [SYSTEM] Thinking level set to ${formattedLevel}${isBypass ? ` (Bypass Activated \u{1F575}\uFE0F${s2})` : ""}`, isMeta: true }];
|
|
5499
5591
|
});
|
|
5500
5592
|
}
|
|
5501
5593
|
} else {
|
|
@@ -6678,7 +6770,7 @@ var init_app = __esm({
|
|
|
6678
6770
|
packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
|
|
6679
6771
|
packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
|
|
6680
6772
|
versionFluxflow = packageJson.version;
|
|
6681
|
-
updatedOn = "2026-05-
|
|
6773
|
+
updatedOn = "2026-05-20";
|
|
6682
6774
|
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(
|
|
6683
6775
|
CommandMenu,
|
|
6684
6776
|
{
|