fluxflow-cli 1.11.0 → 1.11.2
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 +114 -48
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -1095,7 +1095,7 @@ ${TOOL_PROTOCOL(mode)}
|
|
|
1095
1095
|
${projectContextBlock}
|
|
1096
1096
|
|
|
1097
1097
|
-- MEMORY RULES --
|
|
1098
|
-
- Memory: ${isMemoryEnabled ? "Use to subtly personalize. Auto Saves" : "OFF. Decline
|
|
1098
|
+
- Memory: ${isMemoryEnabled ? "Use to subtly personalize. Auto Saves" : "OFF. Decline saving new memories"}
|
|
1099
1099
|
- Time: Logs are timestamped. RELATIVE TIME REFERENCE e.g. few mins ago
|
|
1100
1100
|
|
|
1101
1101
|
-- SECURITY RULES --
|
|
@@ -1109,7 +1109,7 @@ ${projectContextBlock}
|
|
|
1109
1109
|
|
|
1110
1110
|
-- RESPONSE RULES --
|
|
1111
1111
|
- End with [turn: continue] for more steps or [turn: finish] when done
|
|
1112
|
-
-
|
|
1112
|
+
- Tool Called? No post tool chat until [turn: continue]
|
|
1113
1113
|
- Task Complete? End loop with [turn: finish]
|
|
1114
1114
|
[/SYSTEM]`.trim();
|
|
1115
1115
|
};
|
|
@@ -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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1541
|
-
|
|
1542
|
-
|
|
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
|
|
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
|
|
1566
|
-
const
|
|
1567
|
-
if (
|
|
1568
|
-
limit =
|
|
1569
|
-
} else if (
|
|
1570
|
-
limit = Math.min(0.025,
|
|
1571
|
-
} else if (
|
|
1572
|
-
limit = Math.min(0.025,
|
|
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,
|
|
1591
|
+
limit = Math.min(0.025, prevLimit2 + 2e-3);
|
|
1575
1592
|
}
|
|
1576
1593
|
}
|
|
1577
1594
|
}
|
|
1578
|
-
const ratio = limit > 0 ?
|
|
1579
|
-
history.push({ limit,
|
|
1595
|
+
const ratio = limit > 0 ? bucket.spent / limit : 0;
|
|
1596
|
+
history.push({ limit, spent: bucket.spent, ratio });
|
|
1580
1597
|
}
|
|
1581
|
-
|
|
1598
|
+
const lastBucket = buckets[buckets.length - 1];
|
|
1599
|
+
if (now < lastBucket.end) {
|
|
1582
1600
|
return history[history.length - 1].limit;
|
|
1583
1601
|
}
|
|
1584
|
-
|
|
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
|
|
1605
|
-
|
|
1606
|
-
|
|
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
|
|
1617
|
-
|
|
1618
|
-
|
|
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
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
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,
|
|
@@ -3740,6 +3799,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3740
3799
|
let toolCallPointer = 0;
|
|
3741
3800
|
let isThinkingLoop = false;
|
|
3742
3801
|
let isStutteringLoop = false;
|
|
3802
|
+
let isGeneralLoop = false;
|
|
3743
3803
|
let isInitialAttempt = true;
|
|
3744
3804
|
let accumulatedContext = "";
|
|
3745
3805
|
let dedupeBuffer = "";
|
|
@@ -3964,6 +4024,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
|
|
|
3964
4024
|
if (respRepetitionRatio > repetitionThresholdResponse) {
|
|
3965
4025
|
yield { type: "status", content: `Response Loop Detected. Re-centering...` };
|
|
3966
4026
|
isThinkingLoop = false;
|
|
4027
|
+
isGeneralLoop = true;
|
|
3967
4028
|
await new Promise((resolve) => setTimeout(resolve, 3e3));
|
|
3968
4029
|
break;
|
|
3969
4030
|
}
|
|
@@ -4237,8 +4298,10 @@ ${boxBottom}` };
|
|
|
4237
4298
|
const hasFinish2 = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText2.toLowerCase());
|
|
4238
4299
|
const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
|
|
4239
4300
|
const didCallTool = toolResults.length > 0 || lastToolSniffed !== null;
|
|
4240
|
-
|
|
4241
|
-
|
|
4301
|
+
const pureOutputText = signalSafeText2.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
|
|
4302
|
+
const endsNormally = /[.!?}"'`’“”]$|```$/s.test(pureOutputText);
|
|
4303
|
+
if (!hasFinish2 && !hasContinue && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
|
|
4304
|
+
throw new Error("Silent stream cutoff (500): Model stream closed cleanly but cut off mid-sentence without signals.");
|
|
4242
4305
|
}
|
|
4243
4306
|
success = true;
|
|
4244
4307
|
await incrementUsage("agent");
|
|
@@ -4317,6 +4380,8 @@ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
4317
4380
|
} else {
|
|
4318
4381
|
if (retryCount <= MAX_RETRIES) {
|
|
4319
4382
|
retryCount++;
|
|
4383
|
+
inStreamRetryCount = 1;
|
|
4384
|
+
accumulatedContext = "";
|
|
4320
4385
|
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 32e3);
|
|
4321
4386
|
isInitialAttempt = true;
|
|
4322
4387
|
yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
@@ -4379,6 +4444,7 @@ ${timestamp}`;
|
|
|
4379
4444
|
modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop ? " for current EFFORT_LEVEL" : ""}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
|
|
4380
4445
|
isThinkingLoop = false;
|
|
4381
4446
|
isStutteringLoop = false;
|
|
4447
|
+
isGeneralLoop = false;
|
|
4382
4448
|
}
|
|
4383
4449
|
}
|
|
4384
4450
|
yield { type: "status", content: null };
|