fluxflow-cli 1.8.21 → 1.8.24
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 +168 -145
- package/package.json +1 -1
package/dist/fluxflow.js
CHANGED
|
@@ -737,10 +737,10 @@ Use tools contextually when needed, don't flood with unnecessary tool calls.
|
|
|
737
737
|
var JANITOR_TOOLS_PROTOCOL;
|
|
738
738
|
var init_janitor_tools = __esm({
|
|
739
739
|
"src/data/janitor_tools.js"() {
|
|
740
|
-
JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle =
|
|
740
|
+
JANITOR_TOOLS_PROTOCOL = (isMemoryEnabled = true, needTitle = true) => `
|
|
741
741
|
${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
|
|
742
742
|
1. YOU MUST UPDATE CHAT TITLE (URGENT PRIORITY):
|
|
743
|
-
tool:functions.chat(title='<short
|
|
743
|
+
tool:functions.chat(title='<short creative title of FULL conversation in 3-5 words>')
|
|
744
744
|
-- END CHAT MANAGEMENT TOOLS --
|
|
745
745
|
|
|
746
746
|
` : ""}
|
|
@@ -748,7 +748,7 @@ ${needTitle ? `-- START CHAT MANAGEMENT TOOLS --
|
|
|
748
748
|
Your tool syntax is: 'tool:functions.function_name(args...)'
|
|
749
749
|
You have access to the following memory functions to persist important information:
|
|
750
750
|
|
|
751
|
-
1. Temporary context (
|
|
751
|
+
1. Temporary context (URGENT PRIORITY):
|
|
752
752
|
tool:functions.memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')
|
|
753
753
|
|
|
754
754
|
${isMemoryEnabled ? `2. User-specific long-term memory (USE BASED ON CONVERSATION CONTEXT):
|
|
@@ -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)}
|
|
@@ -891,7 +891,7 @@ When you 'finish' an agentic loop, you will lose your previous turn 'thinking' d
|
|
|
891
891
|
Current date and Time is: ${dateTimeStr}
|
|
892
892
|
--- END SYSTEM INSTRUCTION ---`.trim();
|
|
893
893
|
};
|
|
894
|
-
getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle =
|
|
894
|
+
getJanitorInstruction = (originalText, agentRaws, userMemories = "", isMemoryEnabled = true, needTitle = true) => {
|
|
895
895
|
let agentRes = `${agentRaws.replace(/tool:functions\..*\n/g, "").replace(/<think>.*<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL_RESULTS\]/g, "").replace(/\[tool_results\]/g, "").substring(0, 3500)}`;
|
|
896
896
|
if (agentRes.length > 3500) {
|
|
897
897
|
agentRes += "\n... (truncated) ...";
|
|
@@ -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,135 @@ var init_ai = __esm({
|
|
|
2465
2465
|
signalTermination = () => {
|
|
2466
2466
|
TERMINATION_SIGNAL = true;
|
|
2467
2467
|
};
|
|
2468
|
+
runJanitorTask = async (settings, agentText, fullAgentTextRaw, history, 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
|
+
const janitorPrompt = getJanitorInstruction(
|
|
2480
|
+
agentText,
|
|
2481
|
+
cleanedFullResponse,
|
|
2482
|
+
janitorUserMemories,
|
|
2483
|
+
isMemoryEnabled,
|
|
2484
|
+
true
|
|
2485
|
+
);
|
|
2486
|
+
janitorContents.push({ role: "user", parts: [{ text: janitorPrompt }] });
|
|
2487
|
+
let finalSynthesis = "";
|
|
2488
|
+
let attempts = 0;
|
|
2489
|
+
const MAX_JANITOR_RETRIES = 2;
|
|
2490
|
+
while (attempts <= MAX_JANITOR_RETRIES) {
|
|
2491
|
+
try {
|
|
2492
|
+
if (!await checkQuota("background", settings)) {
|
|
2493
|
+
console.warn("Quota Exhausted for Background Model. Skipping refinement.");
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
let fullContent = "";
|
|
2497
|
+
let lastUsage = null;
|
|
2498
|
+
try {
|
|
2499
|
+
const timeoutPromise = new Promise(
|
|
2500
|
+
(_, reject) => setTimeout(() => reject(new Error("JANITOR_TIMEOUT")), attempts === 1 ? 25e3 : attempts === 2 ? 2e4 : 3e4)
|
|
2501
|
+
);
|
|
2502
|
+
const streamPromise = (async () => {
|
|
2503
|
+
const stream = await client.models.generateContentStream({
|
|
2504
|
+
model: janitorModel || "gemma-4-26b-a4b-it",
|
|
2505
|
+
contents: janitorContents,
|
|
2506
|
+
config: {
|
|
2507
|
+
maxOutputTokens: 384,
|
|
2508
|
+
temperature: 0.69,
|
|
2509
|
+
safetySettings: [
|
|
2510
|
+
{ category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2511
|
+
{ category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2512
|
+
{ category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
|
|
2513
|
+
{ category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
|
|
2514
|
+
],
|
|
2515
|
+
thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MINIMAL }
|
|
2516
|
+
}
|
|
2517
|
+
});
|
|
2518
|
+
await incrementUsage("background");
|
|
2519
|
+
const iterator2 = stream[Symbol.asyncIterator]();
|
|
2520
|
+
const firstResult2 = await iterator2.next();
|
|
2521
|
+
return { iterator: iterator2, firstResult: firstResult2 };
|
|
2522
|
+
})();
|
|
2523
|
+
const { iterator, firstResult } = await Promise.race([streamPromise, timeoutPromise]);
|
|
2524
|
+
let { value: firstChunk, done: firstDone } = firstResult;
|
|
2525
|
+
if (!firstDone && firstChunk) {
|
|
2526
|
+
const parts = firstChunk.candidates?.[0]?.content?.parts;
|
|
2527
|
+
const chunkText = parts?.[1]?.text || parts?.[0]?.text || (typeof firstChunk.text === "function" ? firstChunk.text() : "");
|
|
2528
|
+
if (chunkText) {
|
|
2529
|
+
fullContent += chunkText;
|
|
2530
|
+
}
|
|
2531
|
+
lastUsage = firstChunk.usageMetadata;
|
|
2532
|
+
for await (const chunk of { [Symbol.asyncIterator]: () => iterator }) {
|
|
2533
|
+
const p = chunk.candidates?.[0]?.content?.parts;
|
|
2534
|
+
const t = p?.[1]?.text || p?.[0]?.text || (typeof chunk.text === "function" ? chunk.text() : "");
|
|
2535
|
+
if (t) fullContent += t;
|
|
2536
|
+
lastUsage = chunk.usageMetadata;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
} catch (e) {
|
|
2540
|
+
if (e.message === "JANITOR_TIMEOUT") {
|
|
2541
|
+
console.error("Janitor API Timeout: No tokens received within 30s.");
|
|
2542
|
+
}
|
|
2543
|
+
throw e;
|
|
2544
|
+
}
|
|
2545
|
+
if (fullContent) {
|
|
2546
|
+
finalSynthesis = fullContent;
|
|
2547
|
+
if (lastUsage) await addToUsage("tokens", lastUsage.totalTokenCount || 0);
|
|
2548
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2549
|
+
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
2550
|
+
if (!fs16.existsSync(janitorLogDir)) fs16.mkdirSync(janitorLogDir, { recursive: true });
|
|
2551
|
+
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `
|
|
2552
|
+
|
|
2553
|
+
---------------------------------------------------
|
|
2554
|
+
|
|
2555
|
+
|
|
2556
|
+
DEBUG [${date}]: ${finalSynthesis}
|
|
2557
|
+
|
|
2558
|
+
`);
|
|
2559
|
+
} else {
|
|
2560
|
+
throw new Error("No synthesis generated by Janitor.");
|
|
2561
|
+
}
|
|
2562
|
+
if (onBackgroundIncrement) onBackgroundIncrement();
|
|
2563
|
+
const janitorToolCalls = detectToolCalls(finalSynthesis);
|
|
2564
|
+
for (const janitorToolCall of janitorToolCalls) {
|
|
2565
|
+
const toolContext = { chatId, sessionId: chatId, history };
|
|
2566
|
+
const result = await dispatchTool(janitorToolCall.toolName, janitorToolCall.args, toolContext);
|
|
2567
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2568
|
+
const janitorLogDir = path16.join(LOGS_DIR, "janitor");
|
|
2569
|
+
fs16.appendFileSync(path16.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${janitorToolCall.toolName}]: ${result}
|
|
2570
|
+
`);
|
|
2571
|
+
if (janitorToolCall.toolName === "memory" && !janitorToolCall.args.includes("action='temp'")) {
|
|
2572
|
+
if (onMemoryUpdated) onMemoryUpdated();
|
|
2573
|
+
}
|
|
2574
|
+
}
|
|
2575
|
+
break;
|
|
2576
|
+
} catch (janitorErr) {
|
|
2577
|
+
attempts++;
|
|
2578
|
+
const date = (/* @__PURE__ */ new Date()).toLocaleString();
|
|
2579
|
+
const janitorErrDir = path16.join(LOGS_DIR, "janitor");
|
|
2580
|
+
if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
|
|
2581
|
+
fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
|
|
2582
|
+
|
|
2583
|
+
`);
|
|
2584
|
+
if (attempts > MAX_JANITOR_RETRIES) break;
|
|
2585
|
+
const backoff = Math.min(1e3 * Math.pow(2, attempts - 1), 5e3);
|
|
2586
|
+
await new Promise((resolve) => setTimeout(resolve, backoff));
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
2589
|
+
if (attempts) {
|
|
2590
|
+
const janitorErrDir = path16.join(LOGS_DIR, "janitor");
|
|
2591
|
+
fs16.appendFileSync(path16.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
|
|
2592
|
+
|
|
2593
|
+
|
|
2594
|
+
`);
|
|
2595
|
+
}
|
|
2596
|
+
};
|
|
2468
2597
|
getActiveToolContext = (text) => {
|
|
2469
2598
|
const toolRegex = /(?:\[?\s*tool:functions\.)([a-z0-9_]+)\s*\(/gi;
|
|
2470
2599
|
let match;
|
|
@@ -2736,10 +2865,10 @@ var init_ai = __esm({
|
|
|
2736
2865
|
throw new Error("Error: Daily Quota Exausted for Agent");
|
|
2737
2866
|
}
|
|
2738
2867
|
let targetModel = modelName;
|
|
2739
|
-
if (retryCount ===
|
|
2868
|
+
if (retryCount === 7) {
|
|
2740
2869
|
targetModel = "gemini-3-flash-preview";
|
|
2741
2870
|
yield { type: "model_update", content: "Trying with fallback model" };
|
|
2742
|
-
} else if (retryCount >=
|
|
2871
|
+
} else if (retryCount >= 8) {
|
|
2743
2872
|
targetModel = "gemini-3.1-flash-lite-preview";
|
|
2744
2873
|
yield { type: "model_update", content: "Trying with fallback model lite" };
|
|
2745
2874
|
} else if (retryCount > 0) {
|
|
@@ -3069,7 +3198,7 @@ ${boxBottom}
|
|
|
3069
3198
|
if (turnText.trim().length > 0) {
|
|
3070
3199
|
if (inStreamRetryCount <= MAX_RETRIES) {
|
|
3071
3200
|
inStreamRetryCount++;
|
|
3072
|
-
const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1),
|
|
3201
|
+
const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 16e3);
|
|
3073
3202
|
modifiedHistory.push({ role: "agent", text: turnText });
|
|
3074
3203
|
if (toolResults.length > 0) {
|
|
3075
3204
|
toolResults.forEach((tr) => modifiedHistory.push(tr));
|
|
@@ -3078,20 +3207,20 @@ ${boxBottom}
|
|
|
3078
3207
|
accumulatedContext += turnText;
|
|
3079
3208
|
yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
3080
3209
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
3081
|
-
} else {
|
|
3082
3210
|
yield { type: "status", content: `Error Occured. Recovering Stream...` };
|
|
3211
|
+
} else {
|
|
3083
3212
|
throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
|
|
3084
3213
|
Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
3085
3214
|
}
|
|
3086
3215
|
} else {
|
|
3087
3216
|
if (retryCount <= MAX_RETRIES) {
|
|
3088
3217
|
retryCount++;
|
|
3089
|
-
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1),
|
|
3218
|
+
const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 16e3);
|
|
3090
3219
|
isInitialAttempt = true;
|
|
3091
3220
|
yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
|
|
3092
3221
|
await new Promise((resolve) => setTimeout(resolve, waitTime));
|
|
3093
|
-
} else {
|
|
3094
3222
|
yield { type: "status", content: `Retrying Connection...` };
|
|
3223
|
+
} else {
|
|
3095
3224
|
throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
|
|
3096
3225
|
Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
3097
3226
|
}
|
|
@@ -3115,128 +3244,17 @@ Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
|
|
|
3115
3244
|
const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
|
|
3116
3245
|
let isActuallyFinished = hasFinish && !shouldContinue;
|
|
3117
3246
|
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
3247
|
const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
|
|
3124
3248
|
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
|
-
}
|
|
3249
|
+
yield {
|
|
3250
|
+
type: "interactive_turn_finished",
|
|
3251
|
+
data: {
|
|
3252
|
+
agentText,
|
|
3253
|
+
fullAgentTextRaw,
|
|
3254
|
+
history: [...modifiedHistory],
|
|
3255
|
+
needTitle
|
|
3226
3256
|
}
|
|
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
|
-
}
|
|
3257
|
+
};
|
|
3240
3258
|
const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
|
|
3241
3259
|
const finalWithTime = `${cleanedFullResponse}
|
|
3242
3260
|
|
|
@@ -4377,7 +4395,7 @@ Selection: ${val}`,
|
|
|
4377
4395
|
let toolCallEncounteredInTurn = false;
|
|
4378
4396
|
let toolCallBalance = 0;
|
|
4379
4397
|
let inToolCallString = null;
|
|
4380
|
-
const signalRegex = /\[
|
|
4398
|
+
const signalRegex = /\[?\s*turn\s*:\s*.*?\s*\]?/gi;
|
|
4381
4399
|
for await (const packet of stream) {
|
|
4382
4400
|
if (packet.type === "status") {
|
|
4383
4401
|
setStatusText(packet.content);
|
|
@@ -4401,14 +4419,23 @@ Selection: ${val}`,
|
|
|
4401
4419
|
thinkConsumedInTurn = false;
|
|
4402
4420
|
continue;
|
|
4403
4421
|
}
|
|
4404
|
-
if (packet.type === "
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4422
|
+
if (packet.type === "interactive_turn_finished") {
|
|
4423
|
+
setIsProcessing(false);
|
|
4424
|
+
runJanitorTask(
|
|
4425
|
+
{ profile: profileData, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats },
|
|
4426
|
+
packet.data.agentText,
|
|
4427
|
+
packet.data.fullAgentTextRaw,
|
|
4428
|
+
packet.data.history,
|
|
4429
|
+
packet.data.needTitle,
|
|
4430
|
+
{
|
|
4431
|
+
onMemoryUpdated: () => setMessages((prev) => {
|
|
4432
|
+
const newMsgs = [...prev];
|
|
4433
|
+
if (newMsgs.length > 0) newMsgs[newMsgs.length - 1].memoryUpdated = true;
|
|
4434
|
+
return newMsgs;
|
|
4435
|
+
}),
|
|
4436
|
+
onBackgroundIncrement: () => setSessionBackgroundCalls((prev) => prev + 1)
|
|
4409
4437
|
}
|
|
4410
|
-
|
|
4411
|
-
});
|
|
4438
|
+
);
|
|
4412
4439
|
continue;
|
|
4413
4440
|
}
|
|
4414
4441
|
if (packet.type === "visual_feedback") {
|
|
@@ -4434,10 +4461,6 @@ Selection: ${val}`,
|
|
|
4434
4461
|
setSessionAgentCalls((prev) => prev + 1);
|
|
4435
4462
|
continue;
|
|
4436
4463
|
}
|
|
4437
|
-
if (packet.type === "background_increment") {
|
|
4438
|
-
setSessionBackgroundCalls((prev) => prev + 1);
|
|
4439
|
-
continue;
|
|
4440
|
-
}
|
|
4441
4464
|
if (packet.type === "tool_time") {
|
|
4442
4465
|
setSessionToolTime((prev) => prev + packet.content);
|
|
4443
4466
|
continue;
|
|
@@ -5209,8 +5232,8 @@ var init_app = __esm({
|
|
|
5209
5232
|
init_text();
|
|
5210
5233
|
SESSION_START_TIME = Date.now();
|
|
5211
5234
|
CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
|
|
5212
|
-
versionFluxflow = "1.8.
|
|
5213
|
-
updatedOn = "2026-05-
|
|
5235
|
+
versionFluxflow = "1.8.24";
|
|
5236
|
+
updatedOn = "2026-05-11";
|
|
5214
5237
|
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
5238
|
CommandMenu,
|
|
5216
5239
|
{
|