fluxflow-cli 3.16.0 → 3.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fluxflow.js +145 -106
- package/package.json +3 -2
package/dist/fluxflow.js
CHANGED
|
@@ -52,13 +52,14 @@ __export(paths_exports, {
|
|
|
52
52
|
SETTINGS_FILE: () => SETTINGS_FILE,
|
|
53
53
|
TEMP_MEM_CHAT_FILE: () => TEMP_MEM_CHAT_FILE,
|
|
54
54
|
TEMP_MEM_FILE: () => TEMP_MEM_FILE,
|
|
55
|
-
USAGE_FILE: () => USAGE_FILE
|
|
55
|
+
USAGE_FILE: () => USAGE_FILE,
|
|
56
|
+
USAGE_FILE_OLD: () => USAGE_FILE_OLD
|
|
56
57
|
});
|
|
57
58
|
import os from "os";
|
|
58
59
|
import path from "path";
|
|
59
60
|
import fs from "fs";
|
|
60
61
|
import crypto from "crypto";
|
|
61
|
-
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, LEDGER_ADVANCE_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
62
|
+
var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE_OLD, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, LEDGER_ADVANCE_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
|
|
62
63
|
var init_paths = __esm({
|
|
63
64
|
"src/utils/paths.js"() {
|
|
64
65
|
FLUXFLOW_DIR = path.join(os.homedir(), ".fluxflow");
|
|
@@ -96,7 +97,8 @@ var init_paths = __esm({
|
|
|
96
97
|
SECRET_DIR = path.join(DATA_DIR, "secret");
|
|
97
98
|
HISTORY_FILE = path.join(SECRET_DIR, "history.json");
|
|
98
99
|
HISTORY_DIR = path.join(SECRET_DIR, "history");
|
|
99
|
-
|
|
100
|
+
USAGE_FILE_OLD = path.join(FLUXFLOW_DIR, "usage.json");
|
|
101
|
+
USAGE_FILE = path.join(SECRET_DIR, "usage.json");
|
|
100
102
|
MEMORIES_FILE = path.join(SECRET_DIR, "memories.json");
|
|
101
103
|
TEMP_MEM_FILE = path.join(SECRET_DIR, "memory-temp.json");
|
|
102
104
|
TEMP_MEM_CHAT_FILE = path.join(SECRET_DIR, "temp-memory-chat.json");
|
|
@@ -9187,24 +9189,11 @@ var init_history = __esm({
|
|
|
9187
9189
|
// src/utils/usage.js
|
|
9188
9190
|
import fs10 from "fs-extra";
|
|
9189
9191
|
import path9 from "path";
|
|
9190
|
-
|
|
9191
|
-
var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
9192
|
+
var generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
|
|
9192
9193
|
var init_usage = __esm({
|
|
9193
9194
|
"src/utils/usage.js"() {
|
|
9194
9195
|
init_paths();
|
|
9195
9196
|
init_crypto();
|
|
9196
|
-
getLocalBackupPath = () => {
|
|
9197
|
-
if (process.platform === "win32") {
|
|
9198
|
-
const localAppData = process.env.LOCALAPPDATA || path9.join(os3.homedir(), "AppData", "Local");
|
|
9199
|
-
return path9.join(localAppData, "FxFl", "backups", "backup.json");
|
|
9200
|
-
}
|
|
9201
|
-
if (process.platform === "darwin") {
|
|
9202
|
-
return path9.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
|
|
9203
|
-
}
|
|
9204
|
-
const xdgDataHome = process.env.XDG_DATA_HOME || path9.join(os3.homedir(), ".local", "share");
|
|
9205
|
-
return path9.join(xdgDataHome, "fxfl", "backups", "backup.json");
|
|
9206
|
-
};
|
|
9207
|
-
BACKUP_FILE = getLocalBackupPath();
|
|
9208
9197
|
generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
|
|
9209
9198
|
cachedUsage = null;
|
|
9210
9199
|
writeTimeout = null;
|
|
@@ -9239,10 +9228,16 @@ var init_usage = __esm({
|
|
|
9239
9228
|
return purged;
|
|
9240
9229
|
};
|
|
9241
9230
|
loadUsageFromFile = async () => {
|
|
9242
|
-
const
|
|
9231
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9232
|
+
try {
|
|
9233
|
+
if (!await fs10.exists(USAGE_FILE) && await fs10.exists(USAGE_FILE_OLD)) {
|
|
9234
|
+
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
9235
|
+
await fs10.move(USAGE_FILE_OLD, USAGE_FILE);
|
|
9236
|
+
}
|
|
9237
|
+
} catch (err) {
|
|
9238
|
+
}
|
|
9243
9239
|
const tempFile = USAGE_FILE + ".tmp";
|
|
9244
9240
|
let primaryData = null;
|
|
9245
|
-
let backupData = null;
|
|
9246
9241
|
try {
|
|
9247
9242
|
if (await fs10.exists(tempFile)) {
|
|
9248
9243
|
const rawContent = (await fs10.readFile(tempFile, "utf8")).trim();
|
|
@@ -9284,44 +9279,7 @@ var init_usage = __esm({
|
|
|
9284
9279
|
} catch (err) {
|
|
9285
9280
|
}
|
|
9286
9281
|
}
|
|
9287
|
-
|
|
9288
|
-
if (await fs10.exists(BACKUP_FILE)) {
|
|
9289
|
-
const rawContent = (await fs10.readFile(BACKUP_FILE, "utf8")).trim();
|
|
9290
|
-
if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
|
|
9291
|
-
backupData = JSON.parse(rawContent);
|
|
9292
|
-
} else {
|
|
9293
|
-
backupData = JSON.parse(decryptAes(rawContent));
|
|
9294
|
-
}
|
|
9295
|
-
}
|
|
9296
|
-
} catch (err) {
|
|
9297
|
-
}
|
|
9298
|
-
let resolvedData = null;
|
|
9299
|
-
if (primaryData && backupData) {
|
|
9300
|
-
if (primaryData.saveId !== backupData.saveId) {
|
|
9301
|
-
resolvedData = primaryData;
|
|
9302
|
-
try {
|
|
9303
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9304
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
9305
|
-
} catch (e) {
|
|
9306
|
-
}
|
|
9307
|
-
} else {
|
|
9308
|
-
resolvedData = primaryData;
|
|
9309
|
-
}
|
|
9310
|
-
} else if (primaryData && !backupData) {
|
|
9311
|
-
resolvedData = primaryData;
|
|
9312
|
-
try {
|
|
9313
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9314
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
9315
|
-
} catch (e) {
|
|
9316
|
-
}
|
|
9317
|
-
} else if (!primaryData && backupData) {
|
|
9318
|
-
resolvedData = backupData;
|
|
9319
|
-
try {
|
|
9320
|
-
await fs10.ensureDir(path9.dirname(USAGE_FILE));
|
|
9321
|
-
await fs10.copy(BACKUP_FILE, USAGE_FILE);
|
|
9322
|
-
} catch (e) {
|
|
9323
|
-
}
|
|
9324
|
-
}
|
|
9282
|
+
let resolvedData = primaryData;
|
|
9325
9283
|
if (resolvedData) {
|
|
9326
9284
|
const stats = resolvedData.stats || { ...defaultStats };
|
|
9327
9285
|
const mergedStats = { ...defaultStats, ...stats };
|
|
@@ -9329,28 +9287,32 @@ var init_usage = __esm({
|
|
|
9329
9287
|
mergedStats.imageCalls = [];
|
|
9330
9288
|
}
|
|
9331
9289
|
const history = resolvedData.history || {};
|
|
9332
|
-
|
|
9290
|
+
const purgedHistory = purgeOldHistory(history, today2);
|
|
9291
|
+
if (Object.keys(history).length !== Object.keys(purgedHistory).length) {
|
|
9292
|
+
isDirty = true;
|
|
9293
|
+
}
|
|
9294
|
+
if (resolvedData.date === today2) {
|
|
9333
9295
|
return {
|
|
9334
9296
|
...resolvedData,
|
|
9335
9297
|
stats: mergedStats,
|
|
9336
|
-
history
|
|
9298
|
+
history: purgedHistory
|
|
9337
9299
|
};
|
|
9338
9300
|
} else {
|
|
9339
9301
|
const oldDate = resolvedData.date;
|
|
9340
9302
|
const oldStats = mergedStats;
|
|
9341
|
-
const updatedHistory = { ...
|
|
9303
|
+
const updatedHistory = { ...purgedHistory };
|
|
9342
9304
|
if (oldDate) {
|
|
9343
9305
|
updatedHistory[oldDate] = oldStats;
|
|
9344
9306
|
}
|
|
9345
9307
|
return {
|
|
9346
|
-
date:
|
|
9308
|
+
date: today2,
|
|
9347
9309
|
stats: { ...defaultStats },
|
|
9348
|
-
history: purgeOldHistory(updatedHistory,
|
|
9310
|
+
history: purgeOldHistory(updatedHistory, today2)
|
|
9349
9311
|
};
|
|
9350
9312
|
}
|
|
9351
9313
|
}
|
|
9352
9314
|
return {
|
|
9353
|
-
date:
|
|
9315
|
+
date: today2,
|
|
9354
9316
|
stats: { ...defaultStats },
|
|
9355
9317
|
history: {}
|
|
9356
9318
|
};
|
|
@@ -9433,7 +9395,10 @@ var init_usage = __esm({
|
|
|
9433
9395
|
mergedHistory[dateKey] = diskData.history[dateKey];
|
|
9434
9396
|
}
|
|
9435
9397
|
}
|
|
9436
|
-
cachedUsage.history = mergedHistory;
|
|
9398
|
+
cachedUsage.history = purgeOldHistory(mergedHistory, cachedUsage.date || today);
|
|
9399
|
+
} else if (cachedUsage && cachedUsage.history) {
|
|
9400
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9401
|
+
cachedUsage.history = purgeOldHistory(cachedUsage.history, today2);
|
|
9437
9402
|
}
|
|
9438
9403
|
cachedUsage.saveId = generateSaveId();
|
|
9439
9404
|
const tempFile = USAGE_FILE + ".tmp";
|
|
@@ -9443,11 +9408,6 @@ var init_usage = __esm({
|
|
|
9443
9408
|
await fs10.fsync(fd);
|
|
9444
9409
|
await fs10.close(fd);
|
|
9445
9410
|
await fs10.rename(tempFile, USAGE_FILE);
|
|
9446
|
-
try {
|
|
9447
|
-
await fs10.ensureDir(path9.dirname(BACKUP_FILE));
|
|
9448
|
-
await fs10.copy(USAGE_FILE, BACKUP_FILE);
|
|
9449
|
-
} catch (backupErr) {
|
|
9450
|
-
}
|
|
9451
9411
|
isDirty = false;
|
|
9452
9412
|
lastWriteTime = Date.now();
|
|
9453
9413
|
} catch (e) {
|
|
@@ -9466,6 +9426,9 @@ var init_usage = __esm({
|
|
|
9466
9426
|
};
|
|
9467
9427
|
initUsage = async () => {
|
|
9468
9428
|
cachedUsage = await loadUsageFromFile();
|
|
9429
|
+
if (isDirty) {
|
|
9430
|
+
queueFlush();
|
|
9431
|
+
}
|
|
9469
9432
|
};
|
|
9470
9433
|
forceFlushUsage = async () => {
|
|
9471
9434
|
if (writeTimeout) {
|
|
@@ -9475,10 +9438,10 @@ var init_usage = __esm({
|
|
|
9475
9438
|
await flushUsage();
|
|
9476
9439
|
};
|
|
9477
9440
|
getDailyUsage = async () => {
|
|
9478
|
-
const
|
|
9441
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9479
9442
|
if (!cachedUsage) {
|
|
9480
9443
|
cachedUsage = await loadUsageFromFile();
|
|
9481
|
-
} else if (cachedUsage.date !==
|
|
9444
|
+
} else if (cachedUsage.date !== today2) {
|
|
9482
9445
|
const oldDate = cachedUsage.date;
|
|
9483
9446
|
const oldStats = cachedUsage.stats;
|
|
9484
9447
|
const history = cachedUsage.history || {};
|
|
@@ -9486,9 +9449,9 @@ var init_usage = __esm({
|
|
|
9486
9449
|
history[oldDate] = oldStats;
|
|
9487
9450
|
}
|
|
9488
9451
|
cachedUsage = {
|
|
9489
|
-
date:
|
|
9452
|
+
date: today2,
|
|
9490
9453
|
stats: { ...defaultStats },
|
|
9491
|
-
history: purgeOldHistory(history,
|
|
9454
|
+
history: purgeOldHistory(history, today2)
|
|
9492
9455
|
};
|
|
9493
9456
|
isDirty = true;
|
|
9494
9457
|
await flushUsage();
|
|
@@ -9499,15 +9462,15 @@ var init_usage = __esm({
|
|
|
9499
9462
|
return cachedUsage.stats;
|
|
9500
9463
|
};
|
|
9501
9464
|
getMonthlyUsage = async () => {
|
|
9502
|
-
const
|
|
9465
|
+
const today2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
9503
9466
|
if (!cachedUsage) {
|
|
9504
9467
|
cachedUsage = await loadUsageFromFile();
|
|
9505
9468
|
}
|
|
9506
|
-
if (cachedUsage.date !==
|
|
9469
|
+
if (cachedUsage.date !== today2) {
|
|
9507
9470
|
await getDailyUsage();
|
|
9508
9471
|
}
|
|
9509
9472
|
const history = cachedUsage.history || {};
|
|
9510
|
-
const purgedHistory = purgeOldHistory(history,
|
|
9473
|
+
const purgedHistory = purgeOldHistory(history, today2);
|
|
9511
9474
|
cachedUsage.history = purgedHistory;
|
|
9512
9475
|
const todayStats = cachedUsage.stats || { ...defaultStats };
|
|
9513
9476
|
const summed = { ...defaultStats };
|
|
@@ -9604,17 +9567,17 @@ var init_usage = __esm({
|
|
|
9604
9567
|
queueFlush();
|
|
9605
9568
|
};
|
|
9606
9569
|
getCustomPeriodUsage = async (resetDay = 1) => {
|
|
9607
|
-
const
|
|
9608
|
-
const todayStr =
|
|
9570
|
+
const today2 = /* @__PURE__ */ new Date();
|
|
9571
|
+
const todayStr = today2.toISOString().split("T")[0];
|
|
9609
9572
|
if (!cachedUsage) {
|
|
9610
9573
|
cachedUsage = await loadUsageFromFile();
|
|
9611
9574
|
}
|
|
9612
9575
|
if (cachedUsage.date !== todayStr) {
|
|
9613
9576
|
await getDailyUsage();
|
|
9614
9577
|
}
|
|
9615
|
-
let startYear =
|
|
9616
|
-
let startMonth =
|
|
9617
|
-
const todayDay =
|
|
9578
|
+
let startYear = today2.getFullYear();
|
|
9579
|
+
let startMonth = today2.getMonth();
|
|
9580
|
+
const todayDay = today2.getDate();
|
|
9618
9581
|
if (todayDay < resetDay) {
|
|
9619
9582
|
startMonth -= 1;
|
|
9620
9583
|
if (startMonth < 0) {
|
|
@@ -9928,14 +9891,14 @@ var init_usage = __esm({
|
|
|
9928
9891
|
});
|
|
9929
9892
|
|
|
9930
9893
|
// src/utils/puppeteer_helper.js
|
|
9931
|
-
import
|
|
9894
|
+
import os3 from "os";
|
|
9932
9895
|
import path10 from "path";
|
|
9933
9896
|
import fs11 from "fs";
|
|
9934
9897
|
import { createRequire } from "module";
|
|
9935
9898
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9936
9899
|
function getPuppeteerConfig() {
|
|
9937
|
-
const platform =
|
|
9938
|
-
const arch =
|
|
9900
|
+
const platform = os3.platform();
|
|
9901
|
+
const arch = os3.arch();
|
|
9939
9902
|
let pptrPlatform = "";
|
|
9940
9903
|
let execName = "";
|
|
9941
9904
|
let subDir = "";
|
|
@@ -10272,6 +10235,7 @@ ${finalResults}`;
|
|
|
10272
10235
|
import puppeteer2 from "puppeteer";
|
|
10273
10236
|
import fs13 from "fs";
|
|
10274
10237
|
import path12 from "path";
|
|
10238
|
+
import TurndownService from "turndown";
|
|
10275
10239
|
var web_scrape;
|
|
10276
10240
|
var init_web_scrape = __esm({
|
|
10277
10241
|
"src/tools/web_scrape.js"() {
|
|
@@ -10329,15 +10293,20 @@ var init_web_scrape = __esm({
|
|
|
10329
10293
|
el.removeAttribute(attrName);
|
|
10330
10294
|
}
|
|
10331
10295
|
}
|
|
10332
|
-
|
|
10333
|
-
|
|
10296
|
+
});
|
|
10297
|
+
while (document.querySelector("div, span")) {
|
|
10298
|
+
document.querySelectorAll("div, span").forEach((el) => {
|
|
10299
|
+
if (el.parentNode) {
|
|
10334
10300
|
el.replaceWith(...el.childNodes);
|
|
10335
10301
|
}
|
|
10336
|
-
}
|
|
10302
|
+
});
|
|
10303
|
+
}
|
|
10304
|
+
document.querySelectorAll("br").forEach((br) => {
|
|
10305
|
+
br.replaceWith(document.createTextNode("\n\n"));
|
|
10337
10306
|
});
|
|
10338
10307
|
const pruneEmpty = () => {
|
|
10339
10308
|
let found = false;
|
|
10340
|
-
document.querySelectorAll("
|
|
10309
|
+
document.querySelectorAll("*").forEach((el) => {
|
|
10341
10310
|
if (el.childNodes.length === 0 && !el.innerText.trim()) {
|
|
10342
10311
|
el.remove();
|
|
10343
10312
|
found = true;
|
|
@@ -10349,11 +10318,17 @@ var init_web_scrape = __esm({
|
|
|
10349
10318
|
return document.body.innerHTML;
|
|
10350
10319
|
});
|
|
10351
10320
|
if (!htmlContent) throw new Error("EMPTY_RENDER_RESULT");
|
|
10352
|
-
const cleanedHtml = htmlContent.replace(
|
|
10321
|
+
const cleanedHtml = htmlContent.replace(/<br\s*\/?>/gi, "\n\n").replace(/[ \t]+/g, " ").replace(/>[ \t]+</g, "><").replace(/\n\s+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
10322
|
+
const turndownService = new TurndownService({
|
|
10323
|
+
headingStyle: "atx",
|
|
10324
|
+
codeBlockStyle: "fenced"
|
|
10325
|
+
});
|
|
10326
|
+
const rawMarkdown = turndownService.turndown(cleanedHtml).replace(/\.\s*\n/g, "\n").replace(/ +/g, " ").replace(/\t/g, " ").replace(/\n\s+/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
10327
|
+
const markdown = rawMarkdown.substring(0, 5e4);
|
|
10353
10328
|
await browser.close();
|
|
10354
|
-
return `
|
|
10329
|
+
return `Markdown parsed from [${url}]:
|
|
10355
10330
|
|
|
10356
|
-
${
|
|
10331
|
+
${markdown}${rawMarkdown.length > 5e4 ? "\n\n[TRUNCATED AT 50K CHARS]" : ""}`;
|
|
10357
10332
|
} catch (err) {
|
|
10358
10333
|
lastError = err;
|
|
10359
10334
|
if (browser) await browser.close();
|
|
@@ -10553,7 +10528,7 @@ var init_view_file = __esm({
|
|
|
10553
10528
|
const end = Math.min(totalLines, finalEnd);
|
|
10554
10529
|
const resultLines = lines.slice(start, end);
|
|
10555
10530
|
const header = `File: [${targetPath}] (Showing lines ${start + 1}-${end} of ${totalLines}).`;
|
|
10556
|
-
const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line}`).join("\n");
|
|
10531
|
+
const code = resultLines.map((line, i) => `${String(start + i + 1).padStart(4)}: ${line.trimEnd()}`).join("\n");
|
|
10557
10532
|
return `${header}
|
|
10558
10533
|
|
|
10559
10534
|
${code}`;
|
|
@@ -19503,7 +19478,7 @@ var app_exports = {};
|
|
|
19503
19478
|
__export(app_exports, {
|
|
19504
19479
|
default: () => App
|
|
19505
19480
|
});
|
|
19506
|
-
import
|
|
19481
|
+
import os4 from "os";
|
|
19507
19482
|
import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
|
|
19508
19483
|
import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
|
|
19509
19484
|
import fs30 from "fs-extra";
|
|
@@ -19531,6 +19506,7 @@ function App({ args = [] }) {
|
|
|
19531
19506
|
const [showBridgePromo, setShowBridgePromo] = useState15(false);
|
|
19532
19507
|
const [promoSelectedIndex, setPromoSelectedIndex] = useState15(0);
|
|
19533
19508
|
const suggestionOffsetRef = useRef4(0);
|
|
19509
|
+
const maxScrollRef = useRef4(0);
|
|
19534
19510
|
const persistedModelRef = useRef4(null);
|
|
19535
19511
|
const activeStreamingMsgRef = useRef4(null);
|
|
19536
19512
|
const [renderTick, setRenderTick] = useState15(0);
|
|
@@ -20018,6 +19994,7 @@ function App({ args = [] }) {
|
|
|
20018
19994
|
const [monthlyUsage, setMonthlyUsage] = useState15(null);
|
|
20019
19995
|
const [customPeriodUsage, setCustomPeriodUsage] = useState15(null);
|
|
20020
19996
|
const [statsMode, setStatsMode] = useState15("daily");
|
|
19997
|
+
const [statsScrollOffset, setStatsScrollOffset] = useState15(0);
|
|
20021
19998
|
const PLAYGROUND_CHAT_ID = "flow-playground";
|
|
20022
19999
|
const [chatId, setChatId] = useState15(args.includes("--playground") ? PLAYGROUND_CHAT_ID : generateChatId());
|
|
20023
20000
|
useEffect12(() => {
|
|
@@ -20192,7 +20169,7 @@ function App({ args = [] }) {
|
|
|
20192
20169
|
useEffect12(() => setEscPressCount(0), [input]);
|
|
20193
20170
|
const [messages, rawSetMessages] = useState15(() => {
|
|
20194
20171
|
const logoMsg = { id: "logo-" + Date.now(), role: "system", isLogo: true, isMeta: true };
|
|
20195
|
-
const isHomeDir = process.cwd() ===
|
|
20172
|
+
const isHomeDir = process.cwd() === os4.homedir();
|
|
20196
20173
|
const isSystemDir = (() => {
|
|
20197
20174
|
const cwd = process.cwd().toLowerCase();
|
|
20198
20175
|
if (process.platform === "win32") {
|
|
@@ -20219,7 +20196,7 @@ function App({ args = [] }) {
|
|
|
20219
20196
|
id: "home-warning",
|
|
20220
20197
|
role: "system",
|
|
20221
20198
|
text: `[SECURITY ALERT] HOME DIRECTORY DETECTED`,
|
|
20222
|
-
subText: `You are currently in ${
|
|
20199
|
+
subText: `You are currently in ${os4.homedir()}. Working here is high-risk as the agent may modify system-sensitive configurations. Please open FluxFlow in project folder.`,
|
|
20223
20200
|
isHomeWarning: true
|
|
20224
20201
|
});
|
|
20225
20202
|
}
|
|
@@ -20398,10 +20375,20 @@ function App({ args = [] }) {
|
|
|
20398
20375
|
if (prev === "modelBreakdown") return "daily";
|
|
20399
20376
|
return prev === "daily" ? "monthly" : "daily";
|
|
20400
20377
|
});
|
|
20378
|
+
setStatsScrollOffset(0);
|
|
20401
20379
|
return;
|
|
20402
20380
|
}
|
|
20403
20381
|
if (key.space || inputText === " ") {
|
|
20404
20382
|
setStatsMode((prev) => prev === "modelBreakdown" ? "daily" : "modelBreakdown");
|
|
20383
|
+
setStatsScrollOffset(0);
|
|
20384
|
+
return;
|
|
20385
|
+
}
|
|
20386
|
+
if (key.upArrow) {
|
|
20387
|
+
setStatsScrollOffset((prev) => Math.max(0, prev - 1));
|
|
20388
|
+
return;
|
|
20389
|
+
}
|
|
20390
|
+
if (key.downArrow) {
|
|
20391
|
+
setStatsScrollOffset((prev) => Math.min(maxScrollRef.current, prev + 1));
|
|
20405
20392
|
return;
|
|
20406
20393
|
}
|
|
20407
20394
|
}
|
|
@@ -23196,13 +23183,13 @@ Selection: ${val}`,
|
|
|
23196
23183
|
const limitsNotSet = !usingProviderBudgets && (shouldClearValue(reqLimit) || shouldClearValue(tokenLimit) || shouldClearValue(monthlyLimit));
|
|
23197
23184
|
let resetInfo = "";
|
|
23198
23185
|
if (quotas.resetMode === "Custom") {
|
|
23199
|
-
const
|
|
23186
|
+
const today2 = /* @__PURE__ */ new Date();
|
|
23200
23187
|
const resetDay = quotas.resetDay || 1;
|
|
23201
|
-
let resetMonth =
|
|
23202
|
-
if (
|
|
23188
|
+
let resetMonth = today2.getMonth();
|
|
23189
|
+
if (today2.getDate() >= resetDay) {
|
|
23203
23190
|
resetMonth += 1;
|
|
23204
23191
|
}
|
|
23205
|
-
const resetDate = new Date(
|
|
23192
|
+
const resetDate = new Date(today2.getFullYear(), resetMonth, resetDay);
|
|
23206
23193
|
const monthName = resetDate.toLocaleString("default", { month: "short" });
|
|
23207
23194
|
resetInfo = `${monthName}-${resetDay}`;
|
|
23208
23195
|
}
|
|
@@ -23334,10 +23321,62 @@ Selection: ${val}`,
|
|
|
23334
23321
|
const imageCreditsLabel = statsMode === "monthly" ? "Image Credits:" : "Image Credits:";
|
|
23335
23322
|
const codeChangesLabel = statsMode === "monthly" ? "Code Changes:" : "Code Changes:";
|
|
23336
23323
|
const toolCallsLabel = statsMode === "monthly" ? "Tool Calls:" : "Tool Calls:";
|
|
23337
|
-
|
|
23338
|
-
|
|
23339
|
-
|
|
23340
|
-
})) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Session Duration:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionAgentCalls)), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB API Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Tool Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionBackgroundCalls)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tokens Consumed:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Active Context:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Images Made:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionImageCount)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Image Credits:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Code Changes (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tool Calls (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", runtimeSession.toolSuccess), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", runtimeSession.toolFailure), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )"))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, timeLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.agent || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.background || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, tokensLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imagesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u.imageCalls.length)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imageCreditsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, codeChangesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, toolCallsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )")))), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true, marginTop: 1, italic: true }, "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
|
|
23324
|
+
const maxRows = Math.max(4, (stdout?.rows || terminalSize?.rows || 24) - 15);
|
|
23325
|
+
const renderLeaderRow = (key, leftText, rightText, leftColor, rightColor, indent = 0, isBold = false) => {
|
|
23326
|
+
const cols = stdout?.columns || terminalSize?.columns || 80;
|
|
23327
|
+
const boxWidth = Math.min(125, cols - 2);
|
|
23328
|
+
const lineWidth = Math.max(20, boxWidth - 6);
|
|
23329
|
+
const maxLeftLen = Math.max(5, lineWidth - indent - rightText.length - 5);
|
|
23330
|
+
let cleanLeftText = leftText;
|
|
23331
|
+
if (cleanLeftText.length > maxLeftLen) {
|
|
23332
|
+
cleanLeftText = cleanLeftText.substring(0, maxLeftLen - 1) + "\u2026";
|
|
23333
|
+
}
|
|
23334
|
+
const dotsCount = Math.max(2, lineWidth - indent - cleanLeftText.length - rightText.length - 2);
|
|
23335
|
+
const dotsStr = " " + ".".repeat(dotsCount) + " ";
|
|
23336
|
+
const indentStr = " ".repeat(indent);
|
|
23337
|
+
return /* @__PURE__ */ React16.createElement(Box14, { key, width: lineWidth }, /* @__PURE__ */ React16.createElement(Text16, { wrap: "truncate" }, /* @__PURE__ */ React16.createElement(Text16, null, indentStr), /* @__PURE__ */ React16.createElement(Text16, { color: leftColor, bold: isBold }, cleanLeftText), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true }, dotsStr), /* @__PURE__ */ React16.createElement(Text16, { color: rightColor, bold: isBold }, rightText)));
|
|
23338
|
+
};
|
|
23339
|
+
const breakdownRows = [];
|
|
23340
|
+
if (!monthlyUsage?.models || Object.keys(monthlyUsage.models).length === 0) {
|
|
23341
|
+
breakdownRows.push(
|
|
23342
|
+
/* @__PURE__ */ React16.createElement(Box14, { key: "empty", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, italic: true }, "No model token usage recorded in the last 30 days."))
|
|
23343
|
+
);
|
|
23344
|
+
} else {
|
|
23345
|
+
Object.entries(monthlyUsage.models).forEach(([provider, models], pIdx) => {
|
|
23346
|
+
const providerTotalTokens = Object.values(models).reduce((sum, m) => sum + (m.tokens || 0), 0);
|
|
23347
|
+
if (pIdx > 0) {
|
|
23348
|
+
breakdownRows.push(/* @__PURE__ */ React16.createElement(Box14, { key: `space-prov-${provider}` }, /* @__PURE__ */ React16.createElement(Text16, null, " ")));
|
|
23349
|
+
}
|
|
23350
|
+
breakdownRows.push(
|
|
23351
|
+
renderLeaderRow(`prov-${provider}`, `${provider}:`, formatTokens(providerTotalTokens), colors.primary, colors.text, 0, true)
|
|
23352
|
+
);
|
|
23353
|
+
Object.entries(models).forEach(([modelName, stats], mIdx) => {
|
|
23354
|
+
if (mIdx > 0) {
|
|
23355
|
+
breakdownRows.push(/* @__PURE__ */ React16.createElement(Box14, { key: `space-mod-${provider}-${modelName}` }, /* @__PURE__ */ React16.createElement(Text16, null, " ")));
|
|
23356
|
+
}
|
|
23357
|
+
breakdownRows.push(
|
|
23358
|
+
renderLeaderRow(`mod-${provider}-${modelName}`, `\xBB ${modelName}:`, formatTokens(stats.tokens || 0), colors.secondary, colors.text, 2, true)
|
|
23359
|
+
);
|
|
23360
|
+
breakdownRows.push(
|
|
23361
|
+
renderLeaderRow(`in-${provider}-${modelName}`, "\xBB Input Tokens:", formatTokens((stats.tokens || 0) - (stats.candidateTokens || 0)), colors.textMuted, colors.text, 5, false)
|
|
23362
|
+
);
|
|
23363
|
+
if ((stats.cachedTokens || 0) > 0) {
|
|
23364
|
+
breakdownRows.push(
|
|
23365
|
+
renderLeaderRow(`cache-${provider}-${modelName}`, "\xBB Cached:", formatTokens(stats.cachedTokens), colors.textMuted, colors.text, 7, false)
|
|
23366
|
+
);
|
|
23367
|
+
}
|
|
23368
|
+
breakdownRows.push(
|
|
23369
|
+
renderLeaderRow(`out-${provider}-${modelName}`, "\xBB Output Tokens:", formatTokens(stats.candidateTokens || 0), colors.textMuted, colors.text, 5, false)
|
|
23370
|
+
);
|
|
23371
|
+
});
|
|
23372
|
+
});
|
|
23373
|
+
}
|
|
23374
|
+
const totalRows = breakdownRows.length;
|
|
23375
|
+
const maxScroll = Math.max(0, totalRows - maxRows);
|
|
23376
|
+
maxScrollRef.current = maxScroll;
|
|
23377
|
+
const effectiveScroll = Math.min(statsScrollOffset, maxScroll);
|
|
23378
|
+
const visibleRows = breakdownRows.slice(effectiveScroll, effectiveScroll + maxRows);
|
|
23379
|
+
return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 3, paddingY: 1, paddingBottom: 0, width: Math.min(125, (stdout?.columns || 100) - 2) }, statsMode === "modelBreakdown" ? /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, { justifyContent: "space-between" }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "30-DAY MODEL TOKEN BREAKDOWN"), totalRows > maxRows && /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true }, "[", effectiveScroll + 1, "-", Math.min(totalRows, effectiveScroll + maxRows), " of ", totalRows, "] \u25B2\u25BC")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", height: maxRows, marginTop: 1 }, visibleRows)) : /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginBottom: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column" }, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Session Duration:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionAgentCalls)), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB API Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Tool Time:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionBackgroundCalls)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tokens Consumed:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Active Context:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionStats.tokens))), sessionTotalTokens > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalTokens - sessionTotalCandidateTokens))), sessionTotalCachedTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCachedTokens))), sessionTotalCandidateTokens > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(sessionTotalCandidateTokens)))), sessionImageCount > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Images Made:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, sessionImageCount)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Image Credits:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Code Changes (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", runtimeSession.linesAdded), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", runtimeSession.linesRemoved))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Tool Calls (Sess):")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, runtimeSession.toolSuccess + runtimeSession.toolFailure + runtimeSession.toolDenied, " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", runtimeSession.toolSuccess), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", runtimeSession.toolDenied), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", runtimeSession.toolFailure), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )"))), /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.text, bold: true, underline: true }, trackerTitle), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, timeLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatDuration(u?.duration || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Model Requests:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.agent || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, "Memory Agent:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u?.background || 0)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, tokensLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u?.tokens || 0))), (u?.tokens || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Input Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens((u?.tokens || 0) - (u?.candidateTokens || 0)))), (u?.cachedTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 4 }, /* @__PURE__ */ React16.createElement(Box14, { width: 21 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Cached:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.cachedTokens))), (u?.candidateTokens || 0) > 0 && /* @__PURE__ */ React16.createElement(Box14, { marginLeft: 2 }, /* @__PURE__ */ React16.createElement(Box14, { width: 23 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\xBB Output Tokens:")), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, formatTokens(u.candidateTokens)))), (u?.imageCalls?.length || 0) > 0 && /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imagesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, u.imageCalls.length)), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, imageCreditsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, Number(((u.imageCalls.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, codeChangesLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "+", u?.linesAdded || 0), " ", /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "-", u?.linesRemoved || 0))), /* @__PURE__ */ React16.createElement(Box14, null, /* @__PURE__ */ React16.createElement(Box14, { width: 25 }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.secondary }, toolCallsLabel)), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, (u?.toolSuccess || 0) + (u?.toolFailure || 0) + (u?.toolDenied || 0), " ( "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.success || "green" }, "\u2714 ", u?.toolSuccess || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow" }, "\u{1F6C7} ", u?.toolDenied || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " "), /* @__PURE__ */ React16.createElement(Text16, { color: colors.danger || "red" }, "\u2718 ", u?.toolFailure || 0), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, " )")))), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted, dimColor: true, italic: true }, "\n", "(Press TAB to toggle Daily/Monthly views, SPACE for Model Breakdown, ESC to return)"));
|
|
23341
23380
|
}
|
|
23342
23381
|
case "dynamicDirDanger":
|
|
23343
23382
|
return /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: colors.borderMuted, paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: colors.warning || "yellow", bold: true, underline: true }, "DYNAMIC DIRECTORY AWARENESS"), /* @__PURE__ */ React16.createElement(Text16, { marginTop: 1, color: colors.text }, "Enabling this keeps the agent aware of filesystem state in real time, but may reduce prompt cache efficiency."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.text }, "\n", "RECOMMENDED SCENARIOS TO TURN ON:"), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 Repo is small."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 The task benefits from real-time filesystem awareness."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 Files are often created, renamed, or deleted."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You know exactly what you're signing up for."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You don't have conflicting decisions regarding token bills."), /* @__PURE__ */ React16.createElement(Text16, { color: colors.textMuted }, "\u2022 You want to see your wallet crying at 3am."), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(
|
|
@@ -24142,7 +24181,7 @@ var init_app = __esm({
|
|
|
24142
24181
|
};
|
|
24143
24182
|
getKeybindingsPath = (ideName) => {
|
|
24144
24183
|
const dirName = getIDEDirName(ideName);
|
|
24145
|
-
const home =
|
|
24184
|
+
const home = os4.homedir();
|
|
24146
24185
|
if (process.platform === "win32") {
|
|
24147
24186
|
const appData = process.env.APPDATA;
|
|
24148
24187
|
if (!appData) return null;
|
|
@@ -24401,10 +24440,10 @@ var init_app = __esm({
|
|
|
24401
24440
|
// src/cli.jsx
|
|
24402
24441
|
import { spawn as spawn3 } from "child_process";
|
|
24403
24442
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
24404
|
-
import
|
|
24443
|
+
import os5 from "os";
|
|
24405
24444
|
import dotenv2 from "dotenv";
|
|
24406
24445
|
dotenv2.config({ quiet: true });
|
|
24407
|
-
var totalSystemRamBytes =
|
|
24446
|
+
var totalSystemRamBytes = os5.totalmem();
|
|
24408
24447
|
var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
|
|
24409
24448
|
var SAFETY_MARGIN = 0.5;
|
|
24410
24449
|
var calculatedLimit = Math.floor(totalSystemRamMB * SAFETY_MARGIN);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fluxflow-cli",
|
|
3
|
-
"version": "3.16.
|
|
3
|
+
"version": "3.16.1",
|
|
4
4
|
"date": "2026-08-01",
|
|
5
5
|
"description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
|
|
6
6
|
"keywords": [
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"scripts": {
|
|
43
43
|
"start": "tsx ./src/cli.jsx",
|
|
44
|
-
"build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:@google/genai --external:zod --external:nanoid --external:puppeteer --external:pdf-lib --external:node-pty --external:html-to-docx --external:typescript --external:ws --external:web-tree-sitter --external:diff --external:dotenv --external:fast-glob"
|
|
44
|
+
"build": "esbuild ./src/cli.jsx --bundle --platform=node --format=esm --outfile=./dist/fluxflow.js --external:react --external:ink --external:chalk --external:fs-extra --external:gradient-string --external:ink-text-input --external:ink-select-input --external:@google/genai --external:zod --external:nanoid --external:puppeteer --external:pdf-lib --external:node-pty --external:html-to-docx --external:typescript --external:ws --external:web-tree-sitter --external:diff --external:dotenv --external:fast-glob --external:turndown"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@google/genai": "^1.52.0",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"pdf-lib": "^1.17.1",
|
|
63
63
|
"puppeteer": "24.43.1",
|
|
64
64
|
"react": "^19.2.5",
|
|
65
|
+
"turndown": "^7.2.4",
|
|
65
66
|
"web-tree-sitter": "^0.25.10",
|
|
66
67
|
"ws": "^8.21.0",
|
|
67
68
|
"zod": "^4.3.6"
|