fluxflow-cli 1.12.4 → 1.12.6

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 +53 -31
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -989,16 +989,23 @@ var init_janitor_tools = __esm({
989
989
  Your tool syntax is: '[tool:functions.ToolName(args...)]'
990
990
 
991
991
  -- CHAT MANAGEMENT TOOLS (MUST CALL THESE 2 TOOLS ALWAYS) --
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
- [tool:functions.Memory(action='temp', content='<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]')]
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
+ [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) --
996
- - Add: [tool:functions.Memory(action='user', method='add', content='<string to add>. [Saved on: <date ONLY>]')]
997
- - Delete: [tool:functions.Memory(action='user', method='delete', content='exact memory id')]
998
- - Update: [tool:functions.Memory(action='user', method='update', content-new='string to update', content-old='exact memory id')]
995
+ ${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, PROACTIVE USAGE) --
996
+ - Add: [tool:functions.Memory(action="user", method="add", content="<string to add>. [Saved on: <date ONLY>]")]
997
+ - Delete: [tool:functions.Memory(action="user", method="delete", id="<memory id>")]
998
+ - Update: [tool:functions.Memory(action="user", method="update", content-new="string to update", id="<memory id>")]
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.
999
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
 
@@ -2111,6 +2118,7 @@ var init_memory = __esm({
2111
2118
  const content = parseArg("content");
2112
2119
  const contentNew = parseArg("content-new");
2113
2120
  const contentOld = parseArg("content-old");
2121
+ const id = parseArg("id");
2114
2122
  const chatId = parseArg("chat-id") || context.chatId || context.sessionId || "default-session";
2115
2123
  if (action === "temp") {
2116
2124
  if (!content) return "ERROR: Missing 'content' for temp memory.";
@@ -2130,30 +2138,36 @@ var init_memory = __esm({
2130
2138
  const memories = readEncryptedJson(MEMORIES_FILE, []);
2131
2139
  if (method === "add") {
2132
2140
  if (!content) return "ERROR: Missing 'content' for memory addition.";
2141
+ const now = /* @__PURE__ */ new Date();
2142
+ const dateStr = `${now.getDate()}/${now.getMonth() + 1}/${now.getFullYear()}`;
2143
+ const formattedContent = content.includes("[Saved on:") ? content : `${content.trim()} [Saved on: ${dateStr}]`;
2133
2144
  const MAX_CHARS = 1024 * 4;
2134
2145
  let currentTotalLength = memories.reduce((acc, m) => acc + (m.memory?.length || 0), 0);
2135
- while (memories.length > 0 && currentTotalLength + content.length > MAX_CHARS) {
2146
+ while (memories.length > 0 && currentTotalLength + formattedContent.length > MAX_CHARS) {
2136
2147
  const removed = memories.shift();
2137
2148
  currentTotalLength -= removed.memory?.length || 0;
2138
2149
  }
2139
- const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: content };
2150
+ const newMemory = { id: `mem-${Date.now().toString(36)}`, memory: formattedContent };
2140
2151
  memories.push(newMemory);
2141
2152
  writeEncryptedJson(MEMORIES_FILE, memories);
2142
- return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + content.length} chars)`;
2153
+ return `SUCCESS: Memory added with ID [${newMemory.id}]. (Vault Size: ${currentTotalLength + formattedContent.length} chars)`;
2143
2154
  }
2144
2155
  if (method === "update") {
2145
- const memId = contentOld;
2146
- const newText = contentNew;
2147
- if (!memId || !newText) return "ERROR: Missing 'content-old' (id) or 'content-new' for update.";
2156
+ const memId = id || contentOld;
2157
+ const newText = contentNew || content;
2158
+ if (!memId || !newText) return "ERROR: Missing 'id' or content for update.";
2148
2159
  const index = memories.findIndex((m) => m.id === memId);
2149
2160
  if (index === -1) return `ERROR: Memory ID [${memId}] not found.`;
2150
- memories[index].memory = newText;
2161
+ const now = /* @__PURE__ */ new Date();
2162
+ const dateStr = `${now.getDate()}/${now.getMonth() + 1}/${now.getFullYear()}`;
2163
+ const formattedText = newText.includes("[Saved on:") ? newText : `${newText.trim()} [Saved on: ${dateStr}]`;
2164
+ memories[index].memory = formattedText;
2151
2165
  writeEncryptedJson(MEMORIES_FILE, memories);
2152
2166
  return `SUCCESS: Memory [${memId}] updated.`;
2153
2167
  }
2154
2168
  if (method === "delete") {
2155
- const memId = content;
2156
- if (!memId) return "ERROR: Missing 'content' (id) for deletion.";
2169
+ const memId = id || content;
2170
+ if (!memId) return "ERROR: Missing 'id' for deletion.";
2157
2171
  const initialLen = memories.length;
2158
2172
  const updatedMemories = memories.filter((m) => m.id !== memId);
2159
2173
  if (updatedMemories.length === initialLen) return `ERROR: Memory ID [${memId}] not found.`;
@@ -3510,44 +3524,51 @@ var init_ai = __esm({
3510
3524
  if (process.stdout.isTTY) {
3511
3525
  process.stdout.write(`\x1B]0;Finalizing...\x07`);
3512
3526
  }
3527
+ const USER_CONTEXT_LENGTH = 4 * (1024 * 2);
3528
+ const AGENT_CONTEXT_LENGTH = 4 * (1024 * 8);
3513
3529
  const { onStatus, onMemoryUpdated, onBackgroundIncrement } = callbacks;
3514
3530
  const { profile, thinkingLevel, mode, janitorModel, chatId, systemSettings, sessionStats } = settings;
3515
3531
  const isMemoryEnabled = systemSettings?.memory !== false;
3516
3532
  const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
3517
3533
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
3518
- const janitorContents = history.slice(-12).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:")).map((msg) => {
3519
- 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;
3534
+ const janitorContents = history.slice(0, -1).filter((msg) => msg.text && !msg.text.includes("[TOOL RESULT]") && !msg.text.includes("OBSERVATION:") && !msg.isMeta && !msg.isLogo && !String(msg.id).startsWith("welcome") && !String(msg.id).startsWith("logo")).slice(-18).map((msg) => {
3535
+ let processedText = msg.text.replace(/\[tool:functions\..*?\]/g, "").replace(/<think>[\s\S]*?<\/think>/g, "").replace(/\[Prompted on:.*?\]/g, "").replace(/\[METADATA \(PRIORITY: DYNAMIC\)\] Time: ([^|\n]+)/g, (match, p1) => {
3536
+ return `[METADATA (PRIORITY: DYNAMIC)] Time: ${p1.replace(/:\d{2}/g, "")}`;
3537
+ }).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();
3538
+ const limit = msg.role === "user" ? USER_CONTEXT_LENGTH : AGENT_CONTEXT_LENGTH;
3521
3539
  let truncatedText = processedText.substring(0, limit);
3522
3540
  if (processedText.length > limit) {
3523
3541
  truncatedText += "\n... (truncated) ...";
3524
3542
  }
3543
+ const prefix = msg.role === "user" ? truncatedText.startsWith("[USER]") ? "" : "[USER]: " : truncatedText.startsWith("[AGENT]") ? "" : "[AGENT]: ";
3525
3544
  return {
3526
3545
  role: msg.role === "user" ? "user" : "model",
3527
- parts: [{ text: truncatedText }]
3546
+ parts: [{ text: `${prefix}${truncatedText}` }]
3528
3547
  };
3529
3548
  });
3549
+ const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
3550
+ const hasTitleSignal = agentText.includes("[TITLE-UPDATE]");
3551
+ const thisHas80pChanceOfBeingTrue = Math.random() < 0.8;
3552
+ const needTitle = isFirstPrompt || hasTitleSignal || thisHas80pChanceOfBeingTrue;
3530
3553
  const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
3531
3554
  const janitorPrompt = getJanitorInstruction(
3532
- agentText,
3533
- cleanedFullResponse,
3534
3555
  janitorUserMemories,
3535
3556
  isMemoryEnabled,
3536
- true
3557
+ needTitle
3537
3558
  );
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) {
3559
+ 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)}`;
3560
+ if (agentRes.length > AGENT_CONTEXT_LENGTH) {
3540
3561
  agentRes += "\n... (truncated) ...";
3541
3562
  }
3542
3563
  let originalTextProcessed = agentText.replace(/\[Prompted on:.*?\]/g, "").trim();
3543
3564
  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" : ""}
3565
+ let userPrompt = `[USER]: ${originalTextProcessed.substring(0, USER_CONTEXT_LENGTH)}
3566
+ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n" : ""}
3546
3567
  [AGENT (current turn)]: ${agentRes}`;
3547
3568
  janitorContents.push({ role: "user", parts: [{ text: userPrompt }] });
3548
3569
  let finalSynthesis = "";
3549
3570
  let attempts = 0;
3550
- const MAX_JANITOR_RETRIES = 5;
3571
+ const MAX_JANITOR_RETRIES = 12;
3551
3572
  while (attempts <= MAX_JANITOR_RETRIES) {
3552
3573
  if (process.stdout.isTTY) {
3553
3574
  process.stdout.write(`\x1B]0;Retrying Memory (${attempts + 1})...\x07`);
@@ -4737,7 +4758,8 @@ function MemoryModal({ onClose }) {
4737
4758
  }
4738
4759
  });
4739
4760
  const cleanDisplay = (text) => {
4740
- return text.replace(/\[Saved on: .*?\]/g, "").trim();
4761
+ if (!text) return "";
4762
+ return text.replace(/\[Saved on: .*?\]/g, "").replace(/\\+'/g, "'").trim();
4741
4763
  };
4742
4764
  const s = emojiSpace(2);
4743
4765
  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) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.12.4",
3
+ "version": "1.12.6",
4
4
  "date": "2026-05-22",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [