fluxflow-cli 1.12.3 → 1.12.5

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/ARCHITECTURE.md CHANGED
@@ -15,7 +15,7 @@ The core intelligence of Flux Flow resides in `src/utils/ai.js`. It does not rel
15
15
 
16
16
  The execution flow of a single user prompt follows this loop:
17
17
 
18
- 1. **Context Assembly**: The user's prompt is combined with the system instructions, temporary session context, persistent user memories, and the current chat history. If the history gets too large (e.g., >128k tokens) and compression is disabled, it is gracefully truncated.
18
+ 1. **Context Assembly**: The user's prompt is combined with the system instructions, temporary session context, persistent user memories, and the current chat history. If the history gets too large (e.g., >254k tokens) and compression is disabled, it is gracefully truncated.
19
19
  2. **Stream Processing**: The main loop initiates a streaming request to the Gemini API (`client.models.generateContentStream`). It yields chunks of text and status updates directly back to the React UI as they arrive.
20
20
  3. **Detection & Tool Execution**: Once the stream completes for a given turn, the entire response is scanned for tool calls using a custom regex and bracket-balancing parser (looking for `tool:functions.tool_name(args...)`).
21
21
  - If tools are found, the loop pauses.
package/dist/fluxflow.js CHANGED
@@ -961,7 +961,7 @@ ${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
961
961
  2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
962
962
  3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? -> update_file > write_file
963
963
  4. [tool:functions.PatchFile(path="...", content_to_replace="exact old content", content_to_add="new content")]. Surgical patching. Unsure content_to_replace? -> view_file >> guessing.
964
- 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. MUST HAVE PROPER A4 PAGE BREAKS. HTML/CSS for premium layout (100vh/vw). No manual footers
964
+ 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. **USE PROPER PROACTIVE A4 PAGE BREAKS**. HTML/CSS for PREMIUM layout (100vh/vw). No manual footers
965
965
  6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
966
966
  7. [tool:functions.Run(command="...")]. Runs a shell command. Destructive/Irreversible ops -> ask user
967
967
  8. [tool:functions.SearchKeyword(keyword="...")]. Global search. Finds definitions/logic without reading every file
@@ -992,13 +992,20 @@ Your tool syntax is: '[tool:functions.ToolName(args...)]'
992
992
  [tool:functions.Chat(title='<short creative title of FULL conversation in 3-5 words>')]. Consider full chat context to generate title NOT just latest message.
993
993
  [tool:functions.Memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')]
994
994
 
995
- ${isMemoryEnabled ? `-- User-specific long-term memory (USE BASED ON CONVERSATION CONTEXT) --
995
+ ${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, PROACTIVE USAGE) --
996
996
  - Add: [tool:functions.Memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')]
997
997
  - Delete: [tool:functions.Memory(action='user', method='delete', content='exact memory id')]
998
998
  - Update: [tool:functions.Memory(action='user', method='update', content-new='string to update', content-old='exact memory id')]
999
999
 
1000
+ Explicit Triggers for permanent memory:
1001
+ - User explicitly asks to 'remember' something.
1002
+ - User mentions something important that should be remembered.
1003
+ - User provides information that could be useful for future reference.
1004
+ - User shares personal information or preferences.
1005
+ - User talks about a specific topic that should be remembered.
1006
+
1000
1007
  Usage Rules:
1001
- - Frequency for 'user' action: Only when explicit context from chat is found or explicitly requested by the user.
1008
+ - Frequency for 'user' action: Based on explicit triggers.
1002
1009
  - IF YOU WANT TO SAVE SOMETHING, BUT SIMILAR MEMORY ALREADY EXISTS, USE THE UPDATE METHOD NOT THE ADD METHOD` : ""}`.trim();
1003
1010
  }
1004
1011
  });
@@ -1087,8 +1094,8 @@ ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
1087
1094
  Check these first; these files > training data for project consistency. Safety rules apply` : "";
1088
1095
  return `${nameStr}${nicknameStr}${userInstrStr}
1089
1096
  [SYSTEM (OVERRIDES EVERYTHING)]
1090
- Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
1091
- Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented" : "Conversational & UX-focused"}
1097
+ Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, Humorous, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
1098
+ Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented, Logical" : "Conversational & UX-focused"}
1092
1099
  CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" && mode === "Flux" ? ". PS via CMD" : ""}
1093
1100
  High Priority: [SYSTEM], [STEERING HINT]
1094
1101
 
@@ -3510,6 +3517,8 @@ var init_ai = __esm({
3510
3517
  if (process.stdout.isTTY) {
3511
3518
  process.stdout.write(`\x1B]0;Finalizing...\x07`);
3512
3519
  }
3520
+ const USER_CONTEXT_LENGTH = 4 * (1024 * 2);
3521
+ const AGENT_CONTEXT_LENGTH = 4 * (1024 * 8);
3513
3522
  const { onStatus, onMemoryUpdated, onBackgroundIncrement } = callbacks;
3514
3523
  const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
3515
3524
  const isMemoryEnabled = systemSettings?.memory !== false;
@@ -3517,7 +3526,7 @@ var init_ai = __esm({
3517
3526
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
3518
3527
  const janitorContents = history.slice(-12).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => {
3519
3528
  let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[turn: continue\]/g, "").replace(/\[turn: finish\]/g, "").replace(/\[TOOL RESULTS\]/g, "").replace(/\[tool results\]/g, "").replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
3520
- const limit = msg.role === "user" ? 1500 : 24e3;
3529
+ const limit = msg.role === "user" ? USER_CONTEXT_LENGTH : AGENT_CONTEXT_LENGTH;
3521
3530
  let truncatedText = processedText.substring(0, limit);
3522
3531
  if (processedText.length > limit) {
3523
3532
  truncatedText += "\n... (truncated) ...";
@@ -3535,14 +3544,14 @@ var init_ai = __esm({
3535
3544
  isMemoryEnabled,
3536
3545
  true
3537
3546
  );
3538
- let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/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, 24e3)}`;
3539
- if (agentRes.length > 24e3) {
3547
+ let agentRes = `${cleanedFullResponse.replace(/\[tool:functions\..*?\]/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, AGENT_CONTEXT_LENGTH)}`;
3548
+ if (agentRes.length > AGENT_CONTEXT_LENGTH) {
3540
3549
  agentRes += "\n... (truncated) ...";
3541
3550
  }
3542
3551
  let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
3543
3552
  agentRes = agentRes.replace(/\r?\n\r?\n/g, "\n").replace(/\n\n/g, "\n").replace(/\\n\\n/g, "").trim();
3544
- let userPrompt = `[USER]: ${originalTextProcessed.substring(0, 1500)}
3545
- ${originalTextProcessed.length > 1500 ? "... (truncated) ...\n\n" : ""}
3553
+ let userPrompt = `[USER]: ${originalTextProcessed.substring(0, USER_CONTEXT_LENGTH)}
3554
+ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n" : ""}
3546
3555
  [AGENT (current turn)]: ${agentRes}`;
3547
3556
  janitorContents.push({ role: "user", parts: [{ text: userPrompt }] });
3548
3557
  let finalSynthesis = "";
@@ -3894,6 +3903,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3894
3903
  yield { type: "status", content: "Connecting..." };
3895
3904
  TERMINATION_SIGNAL = false;
3896
3905
  let fullAgentResponseChunks = [];
3906
+ let wasToolCalledInLastLoop = false;
3897
3907
  modifiedHistory.forEach((msg) => {
3898
3908
  if (msg.text && msg.role === "agent") {
3899
3909
  msg.text = msg.text.replace(/<(think|thought)>[\s\S]*?<\/(think|thought)>/gi, "").trim();
@@ -3932,6 +3942,7 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRIC
3932
3942
  let lastToolFinishedAt = 0;
3933
3943
  let toolResults = [];
3934
3944
  let toolCallPointer = 0;
3945
+ let anyToolExecutedInThisTurn = false;
3935
3946
  let isThinkingLoop = false;
3936
3947
  let isStutteringLoop = false;
3937
3948
  let isGeneralLoop = false;
@@ -4402,6 +4413,7 @@ ${boxBottom}` };
4402
4413
  }
4403
4414
  const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
4404
4415
  toolResults.push({ role: "user", text: aiContent, binaryPart });
4416
+ anyToolExecutedInThisTurn = true;
4405
4417
  let uiContent = `[TOOL RESULT]: ${result || ""}`;
4406
4418
  if (normToolName === "view_file" || normToolName === "web_scrape") {
4407
4419
  uiContent = `[TOOL RESULT]: ${label} (Context Locked for UI Clarity)`;
@@ -4587,14 +4599,19 @@ ${timestamp}`;
4587
4599
  if (isActuallyFinished) break;
4588
4600
  const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
4589
4601
  modifiedHistory.push({ role: "agent", text: nextAgentMsg });
4590
- if (toolResults.length > 0) {
4602
+ if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
4591
4603
  toolResults.forEach((tr) => modifiedHistory.push(tr));
4592
4604
  } else {
4593
- 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."}`}` });
4605
+ if (wasToolCalledInLastLoop) {
4606
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] System executed the tool with no explicit result, continue with your task or use [turn: finish] if completed.` });
4607
+ } else {
4608
+ 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."}`}` });
4609
+ }
4594
4610
  isThinkingLoop = false;
4595
4611
  isStutteringLoop = false;
4596
4612
  isGeneralLoop = false;
4597
4613
  }
4614
+ wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
4598
4615
  }
4599
4616
  yield { type: "status", content: null };
4600
4617
  };
@@ -4729,7 +4746,8 @@ function MemoryModal({ onClose }) {
4729
4746
  }
4730
4747
  });
4731
4748
  const cleanDisplay = (text) => {
4732
- return text.replace(/\[Saved on: .*?\]/g, "").trim();
4749
+ if (!text) return "";
4750
+ return text.replace(/\[Saved on: .*?\]/g, "").replace(/\\+'/g, "'").trim();
4733
4751
  };
4734
4752
  const s = emojiSpace(2);
4735
4753
  return /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: 80 }, /* @__PURE__ */ React8.createElement(Box8, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React8.createElement(Text8, { color: "cyan", bold: true }, "\u{1F9E0} AGENT MEMORY: LONG-TERM KNOWLEDGE")), !isMemoryOn && memories.length > 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, "Memory is currently Off...")) : memories.length === 0 ? /* @__PURE__ */ React8.createElement(Box8, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React8.createElement(Text8, { italic: true, color: "gray" }, isMemoryOn ? "Learning..." : "Memory not available...")) : /* @__PURE__ */ React8.createElement(Box8, { flexDirection: "column" }, memories.map((mem, idx) => {
@@ -5616,7 +5634,7 @@ ${hintText}`, color: "magenta" }];
5616
5634
  if (newMode === "Flow") {
5617
5635
  setThinkingLevel("Fast");
5618
5636
  } else if (newMode === "Flux") {
5619
- setThinkingLevel("Medium");
5637
+ setThinkingLevel("High");
5620
5638
  }
5621
5639
  const s2 = emojiSpace(2);
5622
5640
  setMessages((prev) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.12.3",
4
- "date": "2026-05-21",
3
+ "version": "1.12.5",
4
+ "date": "2026-05-22",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",