fluxflow-cli 1.8.21 → 1.8.23
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 +167 -142
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -740,7 +740,7 @@ var init_janitor_tools = __esm({
|
|
|
740
740
|
JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = false) => `
|
|
741
741
|
${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
|
|
742
742
|
1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY):
|
|
743
|
-
tool:functions.chat(title='<short summary of conversation context in 3-5 words>')
|
|
743
|
+
tool:functions.chat(title='<short summary of conversation FULL context (MINIMUM 7 TURNS) in 3-5 words>')
|
|
744
744
|
-- END CHAT MANAGEMENT TOOLS --
|
|
745
745
|
|
|
746
746
|
` : ""}
|
|
@@ -833,7 +833,7 @@ If you see a [STEERING HINT] from user, give that prompt priority for the task a
|
|
|
833
833
|
-- START THINKING INSTRUCTIONS --
|
|
834
834
|
${thinkingConfig}
|
|
835
835
|
|
|
836
|
-
BEFORE USING ANY TOOL THINKING IS **MANDATORY** WITH TOOL RULES. ALWAYS PRIORITIZE THINKING FIRST BEFORE RESPONDING. YOU ARE **FORBIDDEN** TO JUMP TO RESPONSES FIRST. THINKING IS REQUIRED EVEN WITH CONVERSATIONAL RESPONSES.
|
|
836
|
+
BEFORE USING ANY TOOL THINKING IS **MANDATORY** WITH TOOL RULES. ALWAYS PRIORITIZE THINKING FIRST BEFORE RESPONDING. YOU ARE **FORBIDDEN** TO JUMP TO RESPONSES FIRST. THINKING IS REQUIRED EVEN WITH SIMPLEST CONVERSATIONAL RESPONSES.
|
|
837
837
|
-- END THINKING INSTRUCTIONS --
|
|
838
838
|
|
|
839
839
|
${TOOL_PROTOCOL(mode)}
|
|
@@ -2449,7 +2449,7 @@ var init_terminal = __esm({
|
|
|
2449
2449
|
import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
|
|
2450
2450
|
import path16 from "path";
|
|
2451
2451
|
import fs16 from "fs";
|
|
2452
|
-
var client, TERMINATION_SIGNAL, signalTermination, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
|
|
2452
|
+
var client, TERMINATION_SIGNAL, signalTermination, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, getAIStream;
|
|
2453
2453
|
var init_ai = __esm({
|
|
2454
2454
|
"src/utils/ai.js"() {
|
|
2455
2455
|
init_prompts();
|
|
@@ -2465,6 +2465,137 @@ var init_ai = __esm({
|
|
|
2465
2465
|
signalTermination = () => {
|
|
2466
2466
|
TERMINATION_SIGNAL = true;
|
|
2467
2467
|
};
|
|
2468
|
+
runJanitorTask = async (settings, agentText, fullAgentTextRaw, history, needTitle, callbacks = {}) => {
|
|
2469
|
+
const { onStatus, onMemoryUpdated, onBackgroundIncrement } = callbacks;
|
|
2470
|
+
const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
|
|
2471
|
+
const isMemoryEnabled = systemSettings?.memory !== false;
|
|
2472
|
+
const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
|
|
2473
|
+
const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
|
|
2474
|
+
const janitorContents = history.slice(-6).filter((msg) => msg.text && !msg.text.includes("[TOOL_RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => ({
|
|
2475
|
+
role: msg.role === "user" ? "user" : "model",
|
|
2476
|
+
parts: [{ text: msg.text.replace(/<think>[\s\S]*?<\/think>/g, "").trim() }]
|
|
2477
|
+
}));
|
|
2478
|
+
const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
2479
|
+
let thisRngHas40pChanceToBehave = Math.random() < 0.41;
|
|
2480
|
+
let generateTitle = needTitle || thisRngHas40pChanceToBehave;
|
|
2481
|
+
const janitorPrompt = getJanitorInstruction(
|
|
2482
|
+
agentText,
|
|
2483
|
+
cleanedFullResponse,
|
|
2484
|
+
janitorUserMemories,
|
|
2485
|
+
isMemoryEnabled,
|
|
2486
|
+
generateTitle
|
|
2487
|
+
);
|
|
2488
|
+
janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
|
|
2489
|
+
let finalSynthesis = "";
|
|
2490
|
+
let attempts = 0;
|
|
2491
|
+
const MAX_JANITOR_RETRIES = 2;
|
|
2492
|
+
while (attempts <= MAX_JANITOR_RETRIES) {
|
|
2493
|
+
try {
|
|
2494
|
+
if (!await checkQuota("background", settings)) {
|
|
2495
|
+
console.warn("Quota Exhausted for Background Model. Skipping refinement.");
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
let fullContent = "";
|
|
2499
|
+
let lastUsage = null;
|
|
2500
|
+
try {
|
|
2501
|
+
const timeoutPromise = new Promise(
|
|
2502
|
+
(_, reject) => setTimeout(() => reject(new Error("JANITOR_TIMEOUT")), attempts === 1 ? 25e3 : attempts === 2 ? 2e4 : 3e4)
|
|
2503
|
+
);
|
|
2504
|
+
const streamPromise = (async () => {
|
|
2505
|
+
const stream = await client.models.generateContentStream({
|
|
2506
|
+
model: janitorModel || "gemma-4-26b-a4b-it",
|
|
2507
|
+
contents: janitorContents,
|
|
2508
|
+
config: {
|
|
2509
|
+
maxOutputTokens: 384,
|
|
2510
|
+
temperature: 0.69,
|
|
2511
|
+
safetySettings: [
|
|
2512
|
+
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2513
|
+
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2514
|
+
{ category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2515
|
+
{ category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
|
|
2516
|
+
],
|
|
2517
|
+
thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
|
|
2518
|
+
}
|
|
2519
|
+
});
|
|
2520
|
+
await incrementUsage("background");
|
|
2521
|
+
const iterator2 = stream[Symbol.asyncIterator]();
|
|
2522
|
+
const firstResult2 = await iterator2.next();
|
|
2523
|
+
return { iterator: iterator2, firstResult: firstResult2 };
|
|
2524
|
+
})();
|
|
2525
|
+
const { iterator, firstResult } = await Promise.race([streamPromise, timeoutPromise]);
|
|
2526
|
+
let { value: firstChunk, done: firstDone } = firstResult;
|
|
2527
|
+
if (!firstDone && firstChunk) {
|
|
2528
|
+
const parts = firstChunk.candidates?.[0]?.content?.parts;
|
|
2529
|
+
const chunkText = parts?.[1]?.text || parts?.[0]?.text || (typeof firstChunk.text === "function" ? firstChunk.text() : "");
|
|
2530
|
+
if (chunkText) {
|
|
2531
|
+
fullContent += chunkText;
|
|
2532
|
+
}
|
|
2533
|
+
lastUsage = firstChunk.usageMetadata;
|
|
2534
|
+
for await (const chunk of { [Symbol.asyncIterator]: () => iterator }) {
|
|
2535
|
+
const p = chunk.candidates?.[0]?.content?.parts;
|
|
2536
|
+
const t = p?.[1]?.text || p?.[0]?.text || (typeof chunk.text === "function" ? chunk.text() : "");
|
|
2537
|
+
if (t) fullContent += t;
|
|
2538
|
+
lastUsage = chunk.usageMetadata;
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
} catch (e) {
|
|
2542
|
+
if (e.message === "JANITOR_TIMEOUT") {
|
|
2543
|
+
console.error("Janitor API Timeout: No tokens received within 30s.");
|
|
2544
|
+
}
|
|
2545
|
+
throw e;
|
|
2546
|
+
}
|
|
2547
|
+
if (fullContent) {
|
|
2548
|
+
finalSynthesis = fullContent;
|
|
2549
|
+
if (lastUsage) await addToUsage("tokens", lastUsage.totalTokenCount || 0);
|
|
2550
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2551
|
+
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
2552
|
+
if (!fs16.existsSync(janitorLogDir)) fs16.mkdirSync(janitorLogDir, { recursive: true });
|
|
2553
|
+
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `
|
|
2554
|
+
|
|
2555
|
+
---------------------------------------------------
|
|
2556
|
+
|
|
2557
|
+
|
|
2558
|
+
DEBUG [${date}]: ${finalSynthesis}
|
|
2559
|
+
|
|
2560
|
+
`);
|
|
2561
|
+
} else {
|
|
2562
|
+
throw new Error("No synthesis generated by Janitor.");
|
|
2563
|
+
}
|
|
2564
|
+
if (onBackgroundIncrement) onBackgroundIncrement();
|
|
2565
|
+
const janitorToolCalls = detectToolCalls(finalSynthesis);
|
|
2566
|
+
for (const janitorToolCall of janitorToolCalls) {
|
|
2567
|
+
const toolContext = { chatId, sessionId: chatId, history };
|
|
2568
|
+
const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
|
|
2569
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2570
|
+
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
2571
|
+
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
|
|
2572
|
+
`);
|
|
2573
|
+
if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
|
|
2574
|
+
if (onMemoryUpdated) onMemoryUpdated();
|
|
2575
|
+
}
|
|
2576
|
+
}
|
|
2577
|
+
break;
|
|
2578
|
+
} catch (janitorErr) {
|
|
2579
|
+
attempts++;
|
|
2580
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2581
|
+
const janitorErrDir = path16.join(LOGS_DIR, "janitor");
|
|
2582
|
+
if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
|
|
2583
|
+
fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
|
|
2584
|
+
|
|
2585
|
+
`);
|
|
2586
|
+
if (attempts > MAX_JANITOR_RETRIES) break;
|
|
2587
|
+
const backoff = Math.min(1e3 * Math.pow(2, attempts - 1), 5e3);
|
|
2588
|
+
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
if (attempts >= MAX_JANITOR_RETRIES) {
|
|
2592
|
+
const janitorErrDir = path16.join(LOGS_DIR, "janitor");
|
|
2593
|
+
fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
|
|
2594
|
+
|
|
2595
|
+
|
|
2596
|
+
`);
|
|
2597
|
+
}
|
|
2598
|
+
};
|
|
2468
2599
|
getActiveToolContext = (text) => {
|
|
2469
2600
|
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
2470
2601
|
let match;
|
|
@@ -2736,10 +2867,10 @@ var init_ai = __esm({
|
|
|
2736
2867
|
throw new Error("Error: Daily Quota Exausted for Agent");
|
|
2737
2868
|
}
|
|
2738
2869
|
let targetModel = modelName;
|
|
2739
|
-
if (retryCount ===
|
|
2870
|
+
if (retryCount === 7) {
|
|
2740
2871
|
targetModel = "gemini-3-flash-preview";
|
|
2741
2872
|
yield { type: "model_update", content: "Trying with fallback model" };
|
|
2742
|
-
} else if (retryCount >=
|
|
2873
|
+
} else if (retryCount >= 8) {
|
|
2743
2874
|
targetModel = "gemini-3.1-flash-lite-preview";
|
|
2744
2875
|
yield { type: "model_update", content: "Trying with fallback model lite" };
|
|
2745
2876
|
} else if (retryCount > 0) {
|
|
@@ -3069,7 +3200,7 @@ ${boxBottom}
|
|
|
3069
3200
|
if (turnText.trim().length > 0) {
|
|
3070
3201
|
if (inStreamRetryCount <= MAX_RETRIES) {
|
|
3071
3202
|
inStreamRetryCount++;
|
|
3072
|
-
const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1),
|
|
3203
|
+
const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 16e3);
|
|
3073
3204
|
modifiedHistory.push({ role: "agent", text: turnText });
|
|
3074
3205
|
if (toolResults.length > 0) {
|
|
3075
3206
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
@@ -3078,20 +3209,20 @@ ${boxBottom}
|
|
|
3078
3209
|
accumulatedContext += turnText;
|
|
3079
3210
|
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
3080
3211
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
3081
|
-
} else {
|
|
3082
3212
|
yield { type: "status", content: `Error Occured. Recovering Stream...` };
|
|
3213
|
+
} else {
|
|
3083
3214
|
throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
|
|
3084
3215
|
Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
3085
3216
|
}
|
|
3086
3217
|
} else {
|
|
3087
3218
|
if (retryCount <= MAX_RETRIES) {
|
|
3088
3219
|
retryCount++;
|
|
3089
|
-
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1),
|
|
3220
|
+
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 16e3);
|
|
3090
3221
|
isInitialAttempt = true;
|
|
3091
3222
|
yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
3092
3223
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
3093
|
-
} else {
|
|
3094
3224
|
yield { type: "status", content: `Retrying Connection...` };
|
|
3225
|
+
} else {
|
|
3095
3226
|
throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
3096
3227
|
Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
3097
3228
|
}
|
|
@@ -3115,128 +3246,17 @@ Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
3115
3246
|
const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
|
|
3116
3247
|
let isActuallyFinished = hasFinish && !shouldContinue;
|
|
3117
3248
|
if (isActuallyFinished) {
|
|
3118
|
-
yield { type: "status", content: "Finalizing..." };
|
|
3119
|
-
const janitorContents = history.slice(-3).filter((msg) => msg.text && !msg.text.includes("[TOOL_RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => ({
|
|
3120
|
-
role: msg.role === "user" ? "user" : "model",
|
|
3121
|
-
parts: [{ text: msg.text.replace(/<think>[\s\S]*?<\/think>/g, "").trim() }]
|
|
3122
|
-
}));
|
|
3123
3249
|
const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
|
|
3124
3250
|
const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
|
|
3133
|
-
let finalSynthesis = "";
|
|
3134
|
-
try {
|
|
3135
|
-
if (!await checkQuota("background", settings)) {
|
|
3136
|
-
console.warn("Quota Exhausted for Background Model. Skipping refinement.");
|
|
3137
|
-
throw new Error("QUOTA_BLOCKED");
|
|
3138
|
-
}
|
|
3139
|
-
yield { type: "spinner", content: false };
|
|
3140
|
-
let fullContent = "";
|
|
3141
|
-
let lastUsage2 = null;
|
|
3142
|
-
try {
|
|
3143
|
-
const timeoutPromise = new Promise(
|
|
3144
|
-
(_, reject) => setTimeout(() => reject(new Error("JANITOR_TIMEOUT")), 2e4)
|
|
3145
|
-
);
|
|
3146
|
-
const streamPromise = (async () => {
|
|
3147
|
-
const stream2 = await client.models.generateContentStream({
|
|
3148
|
-
model: janitorModel || "gemma-4-26b-a4b-it",
|
|
3149
|
-
contents: janitorContents,
|
|
3150
|
-
config: {
|
|
3151
|
-
maxOutputTokens: 384,
|
|
3152
|
-
temperature: 0.69,
|
|
3153
|
-
safetySettings: [
|
|
3154
|
-
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
3155
|
-
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
3156
|
-
{ category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
3157
|
-
{ category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
|
|
3158
|
-
],
|
|
3159
|
-
thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
|
|
3160
|
-
}
|
|
3161
|
-
});
|
|
3162
|
-
await incrementUsage("background");
|
|
3163
|
-
const iterator2 = stream2[Symbol.asyncIterator]();
|
|
3164
|
-
const firstResult2 = await iterator2.next();
|
|
3165
|
-
return { iterator: iterator2, firstResult: firstResult2 };
|
|
3166
|
-
})();
|
|
3167
|
-
const { iterator, firstResult } = await Promise.race([streamPromise, timeoutPromise]);
|
|
3168
|
-
let { value: firstChunk, done: firstDone } = firstResult;
|
|
3169
|
-
if (!firstDone && firstChunk) {
|
|
3170
|
-
const parts = firstChunk.candidates?.[0]?.content?.parts;
|
|
3171
|
-
const chunkText = parts?.[1]?.text || parts?.[0]?.text || (typeof firstChunk.text === "function" ? firstChunk.text() : "");
|
|
3172
|
-
if (chunkText) {
|
|
3173
|
-
fullContent += chunkText;
|
|
3174
|
-
yield { type: "status", content: "Finishing..." };
|
|
3175
|
-
}
|
|
3176
|
-
lastUsage2 = firstChunk.usageMetadata;
|
|
3177
|
-
for await (const chunk of { [Symbol.asyncIterator]: () => iterator }) {
|
|
3178
|
-
const p = chunk.candidates?.[0]?.content?.parts;
|
|
3179
|
-
const t = p?.[1]?.text || p?.[0]?.text || (typeof chunk.text === "function" ? chunk.text() : "");
|
|
3180
|
-
if (t) {
|
|
3181
|
-
fullContent += t;
|
|
3182
|
-
}
|
|
3183
|
-
lastUsage2 = chunk.usageMetadata;
|
|
3184
|
-
}
|
|
3185
|
-
}
|
|
3186
|
-
} catch (e) {
|
|
3187
|
-
if (e.message === "JANITOR_TIMEOUT") {
|
|
3188
|
-
throw new Error("Janitor API Timeout: No tokens received within 20s.");
|
|
3189
|
-
}
|
|
3190
|
-
throw e;
|
|
3191
|
-
}
|
|
3192
|
-
yield { type: "spinner", content: true };
|
|
3193
|
-
if (fullContent) {
|
|
3194
|
-
finalSynthesis = fullContent;
|
|
3195
|
-
if (lastUsage2) {
|
|
3196
|
-
await addToUsage("tokens", lastUsage2.totalTokenCount || 0);
|
|
3197
|
-
}
|
|
3198
|
-
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
3199
|
-
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
3200
|
-
if (!fs16.existsSync(janitorLogDir)) {
|
|
3201
|
-
fs16.mkdirSync(janitorLogDir, { recursive: true });
|
|
3202
|
-
}
|
|
3203
|
-
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `
|
|
3204
|
-
|
|
3205
|
-
---------------------------------------------------
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
DEBUG [${date}]: ${finalSynthesis}
|
|
3209
|
-
|
|
3210
|
-
`);
|
|
3211
|
-
} else {
|
|
3212
|
-
throw new Error("No synthesis generated by Janitor.");
|
|
3213
|
-
}
|
|
3214
|
-
yield { type: "background_increment" };
|
|
3215
|
-
const janitorToolCalls = detectToolCalls(finalSynthesis);
|
|
3216
|
-
for (const janitorToolCall of janitorToolCalls) {
|
|
3217
|
-
const toolContext = { chatId, sessionId: chatId, history };
|
|
3218
|
-
const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
|
|
3219
|
-
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
3220
|
-
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
3221
|
-
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
|
|
3222
|
-
`);
|
|
3223
|
-
if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
|
|
3224
|
-
yield { type: "memory_updated" };
|
|
3225
|
-
}
|
|
3251
|
+
yield {
|
|
3252
|
+
type: "interactive_turn_finished",
|
|
3253
|
+
data: {
|
|
3254
|
+
agentText,
|
|
3255
|
+
fullAgentTextRaw,
|
|
3256
|
+
history: [...modifiedHistory],
|
|
3257
|
+
needTitle
|
|
3226
3258
|
}
|
|
3227
|
-
}
|
|
3228
|
-
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
3229
|
-
const janitorErrDir = path16.join(LOGS_DIR, "janitor");
|
|
3230
|
-
if (!fs16.existsSync(janitorErrDir)) {
|
|
3231
|
-
fs16.mkdirSync(janitorErrDir, { recursive: true });
|
|
3232
|
-
}
|
|
3233
|
-
fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `ERROR [${date}]: ${String(janitorErr)}
|
|
3234
|
-
|
|
3235
|
-
----------------------------------------------------------------------
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
`);
|
|
3239
|
-
}
|
|
3259
|
+
};
|
|
3240
3260
|
const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
|
|
3241
3261
|
const finalWithTime = `${cleanedFullResponse}
|
|
3242
3262
|
|
|
@@ -4377,7 +4397,7 @@ Selection: ${val}`,
|
|
|
4377
4397
|
let toolCallEncounteredInTurn = false;
|
|
4378
4398
|
let toolCallBalance = 0;
|
|
4379
4399
|
let inToolCallString = null;
|
|
4380
|
-
const signalRegex = /\[
|
|
4400
|
+
const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
|
|
4381
4401
|
for await (const packet of stream) {
|
|
4382
4402
|
if (packet.type === "status") {
|
|
4383
4403
|
setStatusText(packet.content);
|
|
@@ -4401,14 +4421,23 @@ Selection: ${val}`,
|
|
|
4401
4421
|
thinkConsumedInTurn = false;
|
|
4402
4422
|
continue;
|
|
4403
4423
|
}
|
|
4404
|
-
if (packet.type === "
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4424
|
+
if (packet.type === "interactive_turn_finished") {
|
|
4425
|
+
setIsProcessing(false);
|
|
4426
|
+
runJanitorTask(
|
|
4427
|
+
{ profile: profileData, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats },
|
|
4428
|
+
packet.data.agentText,
|
|
4429
|
+
packet.data.fullAgentTextRaw,
|
|
4430
|
+
packet.data.history,
|
|
4431
|
+
packet.data.needTitle,
|
|
4432
|
+
{
|
|
4433
|
+
onMemoryUpdated: () => setMessages((prev) => {
|
|
4434
|
+
const newMsgs = [...prev];
|
|
4435
|
+
if (newMsgs.length > 0) newMsgs[newMsgs.length - 1].memoryUpdated = true;
|
|
4436
|
+
return newMsgs;
|
|
4437
|
+
}),
|
|
4438
|
+
onBackgroundIncrement: () => setSessionBackgroundCalls((prev) => prev + 1)
|
|
4409
4439
|
}
|
|
4410
|
-
|
|
4411
|
-
});
|
|
4440
|
+
);
|
|
4412
4441
|
continue;
|
|
4413
4442
|
}
|
|
4414
4443
|
if (packet.type === "visual_feedback") {
|
|
@@ -4434,10 +4463,6 @@ Selection: ${val}`,
|
|
|
4434
4463
|
setSessionAgentCalls((prev) => prev + 1);
|
|
4435
4464
|
continue;
|
|
4436
4465
|
}
|
|
4437
|
-
if (packet.type === "background_increment") {
|
|
4438
|
-
setSessionBackgroundCalls((prev) => prev + 1);
|
|
4439
|
-
continue;
|
|
4440
|
-
}
|
|
4441
4466
|
if (packet.type === "tool_time") {
|
|
4442
4467
|
setSessionToolTime((prev) => prev + packet.content);
|
|
4443
4468
|
continue;
|
|
@@ -5209,8 +5234,8 @@ var init_app = __esm({
|
|
|
5209
5234
|
init_text();
|
|
5210
5235
|
SESSION_START_TIME = Date.now();
|
|
5211
5236
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5212
|
-
versionFluxflow = "1.8.
|
|
5213
|
-
updatedOn = "2026-05-
|
|
5237
|
+
versionFluxflow = "1.8.23";
|
|
5238
|
+
updatedOn = "2026-05-11";
|
|
5214
5239
|
ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "magenta", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent already finished the task before your hint was consumed."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
|
|
5215
5240
|
CommandMenu,
|
|
5216
5241
|
{
|