fluxflow-cli 1.11.0 → 1.11.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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +103 -44
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -1171,7 +1171,7 @@ var init_history = __esm({
1171
1171
  loadHistory = async () => {
1172
1172
  if (await fs5.pathExists(HISTORY_FILE)) {
1173
1173
  try {
1174
- return await fs5.readJson(HISTORY_FILE);
1174
+ return readEncryptedJson(HISTORY_FILE, {});
1175
1175
  } catch (e) {
1176
1176
  return {};
1177
1177
  }
@@ -1189,8 +1189,7 @@ var init_history = __esm({
1189
1189
  messages: persistentMessages,
1190
1190
  updatedAt: Date.now()
1191
1191
  };
1192
- await fs5.ensureDir(path4.dirname(HISTORY_FILE));
1193
- await fs5.writeJson(HISTORY_FILE, history, { spaces: 2 });
1192
+ writeEncryptedJson(HISTORY_FILE, history);
1194
1193
  });
1195
1194
  };
1196
1195
  saveChatTitle = async (id, title) => {
@@ -1202,15 +1201,14 @@ var init_history = __esm({
1202
1201
  } else {
1203
1202
  history[id] = { name: title, messages: [], updatedAt: Date.now() };
1204
1203
  }
1205
- await fs5.ensureDir(path4.dirname(HISTORY_FILE));
1206
- await fs5.writeJson(HISTORY_FILE, history, { spaces: 2 });
1204
+ writeEncryptedJson(HISTORY_FILE, history);
1207
1205
  });
1208
1206
  };
1209
1207
  deleteChat = async (id) => {
1210
1208
  return withLock(async () => {
1211
1209
  const history = await loadHistory();
1212
1210
  delete history[id];
1213
- await fs5.writeJson(HISTORY_FILE, history, { spaces: 2 });
1211
+ writeEncryptedJson(HISTORY_FILE, history);
1214
1212
  const temp = readEncryptedJson(TEMP_MEM_FILE, {});
1215
1213
  if (temp[id]) {
1216
1214
  delete temp[id];
@@ -1370,7 +1368,7 @@ var init_history = __esm({
1370
1368
  // src/utils/usage.js
1371
1369
  import fs6 from "fs-extra";
1372
1370
  import path5 from "path";
1373
- var cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
1371
+ var cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
1374
1372
  var init_usage = __esm({
1375
1373
  "src/utils/usage.js"() {
1376
1374
  init_paths();
@@ -1532,23 +1530,42 @@ var init_usage = __esm({
1532
1530
  }
1533
1531
  return true;
1534
1532
  };
1533
+ getImageQuotaBuckets = (imageCalls) => {
1534
+ const hourMs = 60 * 60 * 1e3;
1535
+ if (!imageCalls || imageCalls.length === 0) {
1536
+ return [];
1537
+ }
1538
+ const sortedCalls = [...imageCalls].sort((a, b) => a.timestamp - b.timestamp);
1539
+ const buckets = [];
1540
+ for (const call of sortedCalls) {
1541
+ if (buckets.length > 0) {
1542
+ const lastBucket = buckets[buckets.length - 1];
1543
+ if (call.timestamp >= lastBucket.start && call.timestamp < lastBucket.end) {
1544
+ lastBucket.calls.push(call);
1545
+ lastBucket.spent += call.cost;
1546
+ continue;
1547
+ }
1548
+ }
1549
+ buckets.push({
1550
+ start: call.timestamp,
1551
+ end: call.timestamp + hourMs,
1552
+ calls: [call],
1553
+ spent: call.cost
1554
+ });
1555
+ }
1556
+ return buckets;
1557
+ };
1535
1558
  getImageQuotaLimit = (imageCalls, now) => {
1536
1559
  const hourMs = 60 * 60 * 1e3;
1537
1560
  if (!imageCalls || imageCalls.length === 0) {
1538
1561
  return 0.025;
1539
1562
  }
1540
- const oldestTimestamp = imageCalls[0].timestamp;
1541
- const startTime = Math.min(oldestTimestamp, now - 24 * hourMs);
1542
- const windows = [];
1543
- let currentEnd = now;
1544
- while (currentEnd > startTime) {
1545
- windows.unshift({ start: currentEnd - hourMs, end: currentEnd });
1546
- currentEnd -= hourMs;
1563
+ const buckets = getImageQuotaBuckets(imageCalls);
1564
+ if (buckets.length === 0) {
1565
+ return 0.025;
1547
1566
  }
1548
1567
  const history = [];
1549
- for (const win of windows) {
1550
- const winCalls = imageCalls.filter((c) => c.timestamp >= win.start && c.timestamp < win.end);
1551
- const usage = winCalls.reduce((sum, c) => sum + c.cost, 0);
1568
+ for (const bucket of buckets) {
1552
1569
  let limit = 0.025;
1553
1570
  if (history.length > 0) {
1554
1571
  const prev1 = history[history.length - 1];
@@ -1562,26 +1579,61 @@ var init_usage = __esm({
1562
1579
  if (consecutiveMax) {
1563
1580
  limit = 0.015;
1564
1581
  } else {
1565
- const prevLimit = prev1.limit;
1566
- const prevRatio = prev1.ratio;
1567
- if (prevRatio >= 0.8) {
1568
- limit = prevLimit === 0.015 ? 0.015 : prevLimit;
1569
- } else if (prevRatio < 0.4) {
1570
- limit = Math.min(0.025, prevLimit + 5e-3);
1571
- } else if (prevRatio >= 0.4 && prevRatio < 0.6) {
1572
- limit = Math.min(0.025, prevLimit + 4e-3);
1582
+ const prevLimit2 = prev1.limit;
1583
+ const prevRatio2 = prev1.ratio;
1584
+ if (prevRatio2 >= 0.8) {
1585
+ limit = prevLimit2 === 0.015 ? 0.015 : prevLimit2;
1586
+ } else if (prevRatio2 < 0.4) {
1587
+ limit = Math.min(0.025, prevLimit2 + 5e-3);
1588
+ } else if (prevRatio2 >= 0.4 && prevRatio2 < 0.6) {
1589
+ limit = Math.min(0.025, prevLimit2 + 4e-3);
1573
1590
  } else {
1574
- limit = Math.min(0.025, prevLimit + 2e-3);
1591
+ limit = Math.min(0.025, prevLimit2 + 2e-3);
1575
1592
  }
1576
1593
  }
1577
1594
  }
1578
- const ratio = limit > 0 ? usage / limit : 0;
1579
- history.push({ limit, usage, ratio });
1595
+ const ratio = limit > 0 ? bucket.spent / limit : 0;
1596
+ history.push({ limit, spent: bucket.spent, ratio });
1580
1597
  }
1581
- if (history.length > 0) {
1598
+ const lastBucket = buckets[buckets.length - 1];
1599
+ if (now < lastBucket.end) {
1582
1600
  return history[history.length - 1].limit;
1583
1601
  }
1584
- return 0.025;
1602
+ let currentLimit = history[history.length - 1].limit;
1603
+ let prevLimit = currentLimit;
1604
+ let prevRatio = history[history.length - 1].ratio;
1605
+ let simulatedTime = lastBucket.end;
1606
+ let consecutiveMaxCount = 0;
1607
+ for (let k = history.length - 1; k >= 0; k--) {
1608
+ if (history[k].ratio >= 0.8) {
1609
+ consecutiveMaxCount++;
1610
+ } else {
1611
+ break;
1612
+ }
1613
+ }
1614
+ while (simulatedTime <= now) {
1615
+ let limit = 0.025;
1616
+ const consecutiveMax = consecutiveMaxCount >= 2;
1617
+ if (consecutiveMax) {
1618
+ limit = 0.015;
1619
+ } else {
1620
+ if (prevRatio >= 0.8) {
1621
+ limit = prevLimit === 0.015 ? 0.015 : prevLimit;
1622
+ } else if (prevRatio < 0.4) {
1623
+ limit = Math.min(0.025, prevLimit + 5e-3);
1624
+ } else if (prevRatio >= 0.4 && prevRatio < 0.6) {
1625
+ limit = Math.min(0.025, prevLimit + 4e-3);
1626
+ } else {
1627
+ limit = Math.min(0.025, prevLimit + 2e-3);
1628
+ }
1629
+ }
1630
+ prevLimit = limit;
1631
+ prevRatio = 0;
1632
+ consecutiveMaxCount = 0;
1633
+ simulatedTime += hourMs;
1634
+ currentLimit = limit;
1635
+ }
1636
+ return currentLimit;
1585
1637
  };
1586
1638
  checkImageQuota = async (settings) => {
1587
1639
  const imageSettings = settings.imageSettings || { keyType: "Default", quality: "Low-High" };
@@ -1601,9 +1653,14 @@ var init_usage = __esm({
1601
1653
  stats.imageCalls = [];
1602
1654
  }
1603
1655
  const now = Date.now();
1604
- const oneHourAgo = now - 60 * 60 * 1e3;
1605
- const activeCalls = stats.imageCalls.filter((c) => c.timestamp >= oneHourAgo);
1606
- const totalSpent = activeCalls.reduce((sum, c) => sum + c.cost, 0);
1656
+ const buckets = getImageQuotaBuckets(stats.imageCalls);
1657
+ let totalSpent = 0;
1658
+ if (buckets.length > 0) {
1659
+ const lastBucket = buckets[buckets.length - 1];
1660
+ if (now >= lastBucket.start && now < lastBucket.end) {
1661
+ totalSpent = lastBucket.spent;
1662
+ }
1663
+ }
1607
1664
  const currentLimit = getImageQuotaLimit(stats.imageCalls, now);
1608
1665
  return totalSpent + currentCost <= currentLimit;
1609
1666
  };
@@ -1613,19 +1670,21 @@ var init_usage = __esm({
1613
1670
  stats.imageCalls = [];
1614
1671
  }
1615
1672
  const now = Date.now();
1616
- const oneHourAgo = now - 60 * 60 * 1e3;
1617
- const activeCalls = stats.imageCalls.filter((c) => c.timestamp >= oneHourAgo);
1618
- const totalSpent = activeCalls.reduce((sum, c) => sum + c.cost, 0);
1619
- const currentLimit = getImageQuotaLimit(stats.imageCalls, now);
1620
- const remaining = Math.max(0, currentLimit - totalSpent);
1673
+ const buckets = getImageQuotaBuckets(stats.imageCalls);
1674
+ let activeCalls = [];
1675
+ let totalSpent = 0;
1621
1676
  let nextResetMin = 0;
1622
- let reclaimCost = 0;
1623
- if (activeCalls.length > 0) {
1624
- const earliestCall = activeCalls.reduce((min, c) => c.timestamp < min.timestamp ? c : min, activeCalls[0]);
1625
- const nextResetTimestamp = earliestCall.timestamp + 60 * 60 * 1e3;
1626
- nextResetMin = Math.max(0, Math.ceil((nextResetTimestamp - now) / (60 * 1e3)));
1627
- reclaimCost = earliestCall.cost;
1677
+ if (buckets.length > 0) {
1678
+ const lastBucket = buckets[buckets.length - 1];
1679
+ if (now >= lastBucket.start && now < lastBucket.end) {
1680
+ activeCalls = lastBucket.calls;
1681
+ totalSpent = lastBucket.spent;
1682
+ nextResetMin = Math.max(0, Math.ceil((lastBucket.end - now) / (60 * 1e3)));
1683
+ }
1628
1684
  }
1685
+ const currentLimit = getImageQuotaLimit(stats.imageCalls, now);
1686
+ const remaining = Math.max(0, currentLimit - totalSpent);
1687
+ const reclaimCost = totalSpent;
1629
1688
  return {
1630
1689
  totalSpent,
1631
1690
  remaining,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.11.0",
3
+ "version": "1.11.1",
4
4
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
5
5
  "keywords": [
6
6
  "ai",