fluxflow-cli 1.19.3 → 1.19.4

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 +186 -34
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -1204,7 +1204,7 @@ ${mode === "Flux" ? `- PROJECT TOOLS (path = relative to CWD) -
1204
1204
  - File structure: Real newlines for code formatting`.trim() : `
1205
1205
  - FILE TOOLS ARE NOT AVAILABLE IN FLOW (Tell user,\` /mode flux\` if needed)`.trim()}
1206
1206
 
1207
- - Results: Passed as [TOOL RESULT] (system priority)
1207
+ - Results: Passed as [TOOL RESULT]
1208
1208
  - MAX Tool call stack: STRICTLY 3 per turn`.trim();
1209
1209
  }
1210
1210
  });
@@ -2396,12 +2396,13 @@ var init_thinking_prompts = __esm({
2396
2396
 
2397
2397
  // src/utils/prompts.js
2398
2398
  import fs4 from "fs";
2399
- var getMemoryPrompt, getSystemInstruction, getJanitorInstruction;
2399
+ var cachedProjectContextBlock, getMemoryPrompt, getSystemInstruction, getJanitorInstruction;
2400
2400
  var init_prompts = __esm({
2401
2401
  async "src/utils/prompts.js"() {
2402
2402
  await init_main_tools();
2403
2403
  init_janitor_tools();
2404
2404
  init_thinking_prompts();
2405
+ cachedProjectContextBlock = null;
2405
2406
  getMemoryPrompt = (tempMemories = "", userMemories = "", isMemoryEnabled = true, isContext32k = false) => {
2406
2407
  if (!isMemoryEnabled) return "";
2407
2408
  const tempMemoriesStr = tempMemories?.length > 0 && !isContext32k ? `-- RECENT CONTEXT FROM OTHER CHATS (PRIORITY: DYNAMIC-LOW, FOCUS: Chat Context > Recent) --
@@ -2413,7 +2414,7 @@ ${userMemories}` : "";
2413
2414
  ${parts.join("\n\n")}
2414
2415
  ` : "";
2415
2416
  };
2416
- getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, isMemoryEnabled = true) => {
2417
+ getSystemInstruction = (profile, thinkingLevel, mode, systemSettings, isMemoryEnabled = true, isFirstPrompt = false) => {
2417
2418
  let thinkingConfig = "";
2418
2419
  if (thinkingLevel !== "GEM") {
2419
2420
  let levelKey = thinkingLevel;
@@ -2451,12 +2452,15 @@ ${nicknameStr.length || userInstrStr.length ? "" : "\n"}` : "";
2451
2452
  { name: "design.md", desc: "UI/UX" },
2452
2453
  { name: "architecture.md", desc: "System Structure" }
2453
2454
  ];
2454
- const foundFiles = projectContextFiles.filter((f) => fs4.existsSync(f.name));
2455
- const projectContextBlock = mode === "Flux" && foundFiles.length > 0 ? `
2455
+ if (isFirstPrompt || cachedProjectContextBlock === null) {
2456
+ const foundFiles = projectContextFiles.filter((f) => fs4.existsSync(f.name));
2457
+ cachedProjectContextBlock = mode === "Flux" && foundFiles.length > 0 ? `
2456
2458
  -- PROJECT CONTEXT (Source of Truth) --
2457
2459
  ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
2458
2460
  Check these first; These Files > Training Data. Safety rules apply
2459
2461
  ` : "";
2462
+ }
2463
+ const projectContextBlock = cachedProjectContextBlock;
2460
2464
  return `${nameStr}${nicknameStr}${userInstrStr}[SYSTEM]
2461
2465
  Identity: Flux Flow (by Kushal Roy Chowdhury). Conversational, Sassy${mode === "Flux" ? ", Respectful" : ", Friendly, Humorous, Sarcastic"}, CLI Agent
2462
2466
  Mode: ${mode}${thinkingLevel !== "Fast" ? " (Thinking Mode)" : ""}. ${mode === "Flux" ? "Logical, Highly Detailed, Task-Driven. Prioritizes scalable file/folder structures, modular architecture, clean code abstractions, step-by-step execution. Industry standard latest coding practices/libraries, clean code, Double Check Imports, Client-Server Sync" : "Concise"}
@@ -2465,6 +2469,10 @@ Mode: ${mode}${thinkingLevel !== "Fast" ? " (Thinking Mode)" : ""}. ${mode === "
2465
2469
  - **MANDATORY: MUST END WITH [turn: continue] to CONTINUE loop OR [turn: finish] to END loop**
2466
2470
  - Tool Called? No post tool chat until [turn: continue]
2467
2471
  - NEVER USE [turn: continue] [turn:finish] together
2472
+
2473
+ -- MARKERS --
2474
+ - TOOL SYSTEM: [TOOL RESULT] (system priority)
2475
+ - SYSTEM NOTIFICATION: [SYSTEM], [METADATA] in user turn
2468
2476
  ${thinkingLevel !== "GEM" ? `
2469
2477
  -- THINKING RULES --
2470
2478
  ${thinkingConfig}
@@ -2484,7 +2492,6 @@ ${projectContextBlock}
2484
2492
 
2485
2493
  -- FORMATTING --
2486
2494
  - GFM Supported
2487
- - Tables: Max 4 cols
2488
2495
  - NO LaTeX${mode === "Flux" ? "" : ". Kaomojis"}
2489
2496
  [/SYSTEM]`.trim();
2490
2497
  };
@@ -5473,7 +5480,116 @@ ${newMemoryListStr}
5473
5480
  await RevertManager.startTransaction(chatId, agentText);
5474
5481
  try {
5475
5482
  let modifiedHistory = [...history.slice(0, -1)];
5483
+ const summariesFile = path16.join(SECRET_DIR, "chat-summaries.json");
5484
+ let summaries = readEncryptedJson(summariesFile, {});
5485
+ let chatDataObj = summaries[chatId] || { summary: "", historyLength: 0 };
5486
+ if (typeof chatDataObj === "string") {
5487
+ chatDataObj = { summary: chatDataObj, historyLength: 0 };
5488
+ }
5489
+ const incomingCleanLength = history.filter((m) => (m.role === "user" || m.role === "agent" || m.role === "system") && !String(m.id).startsWith("welcome") && !m.isMeta).length;
5490
+ if (incomingCleanLength < chatDataObj.historyLength) {
5491
+ delete summaries[chatId];
5492
+ writeEncryptedJson(summariesFile, summaries);
5493
+ chatDataObj = { summary: "", historyLength: 0 };
5494
+ }
5476
5495
  if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
5496
+ yield { type: "status", content: "Condensing session context..." };
5497
+ const flattenContext = (hist) => {
5498
+ return hist.filter((m) => (m.role === "user" || m.role === "agent" || m.role === "system") && !String(m.id).startsWith("welcome") && !m.isMeta).map((m) => {
5499
+ const role = m.text?.startsWith("[TOOL RESULT]") ? "TOOL" : m.role === "agent" ? "AGENT" : "USER";
5500
+ return `[${role}]: ${m.text}`;
5501
+ }).join("\n\n");
5502
+ };
5503
+ const runCondenser = async (flattenedText2, oldSummary2) => {
5504
+ const systemInstruction = `You are an expert context condenser. Summarize the provided chat history (which may include previous summaries, user instructions, agent outputs, and tool results) into a detailed, coherent, and highly technical summary of 1000 to 1500 words. Focus on preserving the architectural decisions made, current system state, task progress, and critical code details. Under no circumstances exceed MAX 2000 words.`;
5505
+ const prompt = oldSummary2 ? `Here is the previous summary:
5506
+ ${oldSummary2}
5507
+
5508
+ Here is the new conversation history:
5509
+ ${flattenedText2}
5510
+
5511
+ Provide a new consolidated summary of the entire session.` : `Here is the conversation history:
5512
+ ${flattenedText2}
5513
+
5514
+ Provide a consolidated summary of the entire session.`;
5515
+ try {
5516
+ const response = await client.models.generateContent({
5517
+ model: "gemini-3.1-flash-lite",
5518
+ contents: prompt,
5519
+ config: {
5520
+ systemInstruction,
5521
+ maxOutputTokens: 2048,
5522
+ temperature: 0.3,
5523
+ safetySettings: [
5524
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
5525
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
5526
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
5527
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
5528
+ ],
5529
+ thinkingConfig: { includeThoughts: false, thinkingLevel: ThinkingLevel.MEDIUM }
5530
+ }
5531
+ });
5532
+ return response.text || "";
5533
+ } catch (err) {
5534
+ try {
5535
+ const response = await client.models.generateContent({
5536
+ model: "gemini-2.5-flash",
5537
+ contents: prompt,
5538
+ config: {
5539
+ systemInstruction,
5540
+ maxOutputTokens: 2048,
5541
+ temperature: 0.3,
5542
+ safetySettings: [
5543
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
5544
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
5545
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
5546
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
5547
+ ],
5548
+ thinkingConfig: { includeThoughts: false, thinkingBudget: 8192 }
5549
+ }
5550
+ });
5551
+ return response.text || "";
5552
+ } catch (e) {
5553
+ try {
5554
+ const response = await client.models.generateContent({
5555
+ model: "gemini-2.5-flash-lite",
5556
+ contents: prompt,
5557
+ config: {
5558
+ systemInstruction,
5559
+ maxOutputTokens: 2048,
5560
+ temperature: 0.3,
5561
+ safetySettings: [
5562
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
5563
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
5564
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
5565
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
5566
+ ],
5567
+ thinkingConfig: { includeThoughts: false, thinkingBudget: 8192 }
5568
+ }
5569
+ });
5570
+ return response.text || "";
5571
+ } catch (e2) {
5572
+ return "";
5573
+ }
5574
+ }
5575
+ }
5576
+ };
5577
+ const flattenedText = flattenContext(modifiedHistory);
5578
+ summaries = readEncryptedJson(summariesFile, {});
5579
+ let chatData = summaries[chatId] || { summary: "", historyLength: 0 };
5580
+ if (typeof chatData === "string") {
5581
+ chatData = { summary: chatData, historyLength: 0 };
5582
+ }
5583
+ const oldSummary = chatData.summary || "";
5584
+ const newSummary = await runCondenser(flattenedText, oldSummary);
5585
+ if (newSummary) {
5586
+ chatData.summary = newSummary;
5587
+ summaries[chatId] = chatData;
5588
+ writeEncryptedJson(summariesFile, summaries);
5589
+ modifiedHistory = [];
5590
+ }
5591
+ }
5592
+ if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 255e3) {
5477
5593
  modifiedHistory = getTruncatedHistory(modifiedHistory, 6);
5478
5594
  }
5479
5595
  if (isFirstPrompt && isMemoryEnabled) {
@@ -5733,13 +5849,26 @@ ${newMemoryListStr}
5733
5849
  const cwdMismatch = lastCwd ? lastCwd !== process.cwd() : false;
5734
5850
  chatPaths[chatId] = process.cwd();
5735
5851
  writeEncryptedJson(PATHS_FILE, chatPaths);
5852
+ summaries = readEncryptedJson(summariesFile, {});
5853
+ chatDataObj = summaries[chatId] || { summary: "", historyLength: 0 };
5854
+ if (typeof chatDataObj === "string") {
5855
+ chatDataObj = { summary: chatDataObj, historyLength: 0 };
5856
+ }
5857
+ const currentSummary = typeof chatDataObj === "object" ? chatDataObj.summary || "" : chatDataObj || "";
5858
+ const summaryBlock = currentSummary ? `
5859
+
5860
+ --- CONTEXT SUMMARY OF PREVIOUS TURNS (PRIORITY: HIGH) ---
5861
+ ${currentSummary}
5862
+
5863
+ ` : "";
5736
5864
  let dirStructure = process.cwd() + "\n" + getDirTree(process.cwd(), dynamicMaxDepth);
5737
5865
  const firstUserMsg = `[SYSTEM METADATA (PRIORITY: DYNAMIC), Chat Context >> Metadata] Time: ${dateTimeStr} | v${versionFluxflow2}
5738
5866
  CWD: ${process.cwd()}${cwdMismatch ? ` (CWD Mismatch! Previous Path: ${lastCwd})` : ""}
5739
5867
  **DIRECTORY STRUCTURE**
5740
5868
  ${dirStructure}
5869
+ ${summaryBlock}
5741
5870
  ${memoryPrompt}
5742
- ${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think**\n" : ""}` : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
5871
+ ${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**\n" : ""}` : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
5743
5872
  modifiedHistory.push({ role: "user", text: firstUserMsg });
5744
5873
  let lastUsage = null;
5745
5874
  const MAX_LOOPS = mode === "Flux" ? 70 : 7;
@@ -5770,7 +5899,7 @@ ${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[S
5770
5899
 
5771
5900
  [STEERING HINT]: ${hint}`;
5772
5901
  } else {
5773
- modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think**\n" : ""}` : ""}[STEERING HINT]: ${hint}` });
5902
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CRITICAL PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**\n" : ""}` : ""}[STEERING HINT]: ${hint}` });
5774
5903
  }
5775
5904
  yield { type: "status", content: "Steering Hint Injected." };
5776
5905
  }
@@ -5840,7 +5969,7 @@ ${thinkingLevel != "Fast" ? `${modelName.toLowerCase().startsWith("gemma") ? "[S
5840
5969
  } else if (retryCount > 0) {
5841
5970
  yield { type: "model_update", content: null };
5842
5971
  }
5843
- currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? "GEM" : thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
5972
+ currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? "GEM" : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt);
5844
5973
  const isGemma = modelName && modelName.toLowerCase().startsWith("gemma");
5845
5974
  const lastUserMsg = contents[contents.length - 1];
5846
5975
  if (isGemma) {
@@ -6500,11 +6629,11 @@ ${boxBottom}` };
6500
6629
  if (TERMINATION_SIGNAL) break;
6501
6630
  const signalSafeText2 = (turnText || "").trim();
6502
6631
  const hasFinish2 = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText2.toLowerCase());
6503
- const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
6632
+ const hasContinue2 = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
6504
6633
  const didCallTool = toolResults.length > 0 || lastToolSniffed !== null;
6505
6634
  const pureOutputText = signalSafeText2.replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/gi, "").trim();
6506
6635
  const endsNormally = /[.!?}"'`’“”]$|```$/s.test(pureOutputText);
6507
- if (!hasFinish2 && !hasContinue && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
6636
+ if (!hasFinish2 && !hasContinue2 && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
6508
6637
  throw new Error("Silent stream cutoff (500): Model stream closed cleanly but cut off mid-sentence without signals.");
6509
6638
  }
6510
6639
  success = true;
@@ -6626,7 +6755,7 @@ Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
6626
6755
  if (lastUsage) {
6627
6756
  const total = lastUsage.totalTokenCount || 0;
6628
6757
  const cached = lastUsage.cachedContentTokenCount || 0;
6629
- const candidates = lastUsage.candidatesTokenCount || 0;
6758
+ const candidates = (lastUsage.candidatesTokenCount || 0) + (lastUsage.thoughtsTokenCount || 0);
6630
6759
  await addToUsage("tokens", total);
6631
6760
  if (cached > 0) {
6632
6761
  await addToUsage("cachedTokens", cached);
@@ -6644,10 +6773,11 @@ Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
6644
6773
  }
6645
6774
  const signalSafeText = getSanitizedText(turnText);
6646
6775
  const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
6776
+ const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText.toLowerCase());
6647
6777
  const shouldContinue = toolCallPointer > 0;
6648
6778
  yield { type: "status", content: "Working..." };
6649
6779
  const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
6650
- let isActuallyFinished = hasFinish && !shouldContinue;
6780
+ let isActuallyFinished = hasFinish && !shouldContinue || !shouldContinue && !hasContinue;
6651
6781
  if (isActuallyFinished) {
6652
6782
  const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
6653
6783
  const cleanedFullResponse = fullAgentTextRaw.replace(/(?:<think>|\[think\])[\s\S]*?(?:<\/think>|\[\/think\])/g, "").trim();
@@ -6660,21 +6790,34 @@ Error Log can be found in ${path16.join(LOGS_DIR, "agent", "error.log")}`);
6660
6790
  needTitle
6661
6791
  }
6662
6792
  };
6663
- const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
6664
- const finalWithTime = `${cleanedFullResponse}
6665
-
6666
- ${timestamp}`;
6667
6793
  if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
6668
- modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
6794
+ modifiedHistory[modifiedHistory.length - 1].text = cleanedFullResponse;
6669
6795
  } else {
6670
- modifiedHistory.push({ role: "agent", text: finalWithTime });
6796
+ modifiedHistory.push({ role: "agent", text: cleanedFullResponse });
6797
+ }
6798
+ try {
6799
+ const summariesFile2 = path16.join(SECRET_DIR, "chat-summaries.json");
6800
+ const summaries2 = readEncryptedJson(summariesFile2, {});
6801
+ let existing = summaries2[chatId] || { summary: "", historyLength: 0 };
6802
+ if (typeof existing === "string") {
6803
+ existing = { summary: existing, historyLength: 0 };
6804
+ }
6805
+ const cleanLen = modifiedHistory.filter((m) => (m.role === "user" || m.role === "agent" || m.role === "system") && !String(m.id).startsWith("welcome") && !m.isMeta).length;
6806
+ existing.historyLength = cleanLen;
6807
+ summaries2[chatId] = existing;
6808
+ writeEncryptedJson(summariesFile2, summaries2);
6809
+ } catch (e) {
6671
6810
  }
6672
6811
  }
6673
6812
  if (isActuallyFinished) break;
6674
6813
  const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
6675
6814
  modifiedHistory.push({ role: "agent", text: nextAgentMsg });
6676
6815
  if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
6677
- toolResults.forEach((tr) => modifiedHistory.push(tr));
6816
+ if (toolResults.length > 0) {
6817
+ const combinedText = toolResults.map((tr) => tr.text).join("\n\n");
6818
+ const binaryPart = toolResults.find((tr) => tr.binaryPart)?.binaryPart || null;
6819
+ modifiedHistory.push({ role: "user", text: combinedText, binaryPart });
6820
+ }
6678
6821
  } else {
6679
6822
  if (wasToolCalledInLastLoop) {
6680
6823
  modifiedHistory.push({ role: "user", text: `[SYSTEM] System failed to verify tool execution, Verify tool syntax, proper escaping and try again if failed` });
@@ -8523,12 +8666,30 @@ ${timestamp}` };
8523
8666
  let apiStart = Date.now();
8524
8667
  let isFirstPacket = true;
8525
8668
  try {
8526
- const cleanHistoryForAI = [...messages, userMessage].filter(
8669
+ const rawHistory = [...messages, userMessage].filter(
8527
8670
  (m) => m.role !== "think" && !m.isVisualFeedback && !String(m.id).startsWith("welcome")
8528
- ).map((m) => ({
8529
- ...m,
8530
- text: m.fullText || m.text
8531
- }));
8671
+ );
8672
+ const cleanHistoryForAI = [];
8673
+ rawHistory.forEach((m, idx) => {
8674
+ let text = m.fullText || m.text;
8675
+ if (m.role === "user" && idx < rawHistory.length - 1) {
8676
+ const userIndex = text.lastIndexOf("[USER]");
8677
+ if (userIndex !== -1) {
8678
+ text = text.substring(userIndex + 6).trim();
8679
+ }
8680
+ }
8681
+ if (m.role === "system" && text?.startsWith("[TOOL RESULT]")) {
8682
+ const prev = cleanHistoryForAI[cleanHistoryForAI.length - 1];
8683
+ if (prev && prev.role === "system" && prev.text?.startsWith("[TOOL RESULT]")) {
8684
+ prev.text += "\n\n" + text;
8685
+ return;
8686
+ }
8687
+ }
8688
+ cleanHistoryForAI.push({
8689
+ ...m,
8690
+ text
8691
+ });
8692
+ });
8532
8693
  const stream = getAIStream(
8533
8694
  activeModel,
8534
8695
  cleanHistoryForAI,
@@ -8708,15 +8869,6 @@ Selection: ${val}`,
8708
8869
  if (packet.type === "interactive_turn_finished") {
8709
8870
  setIsProcessing(false);
8710
8871
  hasFiredJanitor = true;
8711
- setMessages((prev) => {
8712
- const aiHistory = packet.data.history;
8713
- return prev.map((msg, idx) => {
8714
- if (aiHistory[idx]) {
8715
- return { ...msg, fullText: aiHistory[idx].text };
8716
- }
8717
- return msg;
8718
- });
8719
- });
8720
8872
  runJanitorTask(
8721
8873
  { profile: profileData, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats },
8722
8874
  packet.data.agentText,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.19.3",
3
+ "version": "1.19.4",
4
4
  "date": "2026-06-03",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [