fluxflow-cli 1.12.6 → 1.12.8

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 +149 -20
  2. package/package.json +2 -2
package/dist/fluxflow.js CHANGED
@@ -464,6 +464,7 @@ var init_ChatLayout = __esm({
464
464
  { cmd: "/clear", desc: "Clear terminal screen" },
465
465
  { cmd: "/resume", desc: "Load previous session" },
466
466
  { cmd: "/save", desc: "Force save current chat" },
467
+ { cmd: "/export", desc: "Export current chat in a .txt file" },
467
468
  { cmd: "/chats", desc: "List all chat sessions" },
468
469
  { cmd: "/image", desc: "Generate images" },
469
470
  { cmd: "/mode", desc: "Toggle Flux/Flow modes" },
@@ -975,7 +976,7 @@ ${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
975
976
  - File structure: Real newlines for code formatting`.trim() : `
976
977
  - DEV TOOLS ARE NOT AVAILABLE IN FLOW MODE`.trim()}
977
978
 
978
- - Results: Passed as [TOOL RESULT] SYSTEM
979
+ - Results: Passed as [TOOL RESULT] (system)
979
980
  - Tool calls: End with [turn: continue]. Only use [turn: finish] after verifying goals
980
981
  - Multi-call: Stack upto 5`.trim();
981
982
  }
@@ -992,7 +993,7 @@ Your tool syntax is: '[tool:functions.ToolName(args...)]'
992
993
  [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
994
  [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
995
 
995
- ${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, PROACTIVE USAGE) --
996
+ ${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, DO NOT RE-SAVE MEMORY WHICH IS ALREADY SAVED) --
996
997
  - Add: [tool:functions.Memory(action="user", method="add", content="<string to add>. [Saved on: <date ONLY>]")]
997
998
  - Delete: [tool:functions.Memory(action="user", method="delete", id="<memory id>")]
998
999
  - Update: [tool:functions.Memory(action="user", method="update", content-new="string to update", id="<memory id>")]
@@ -1060,12 +1061,13 @@ ${parts.join("\n\n")}
1060
1061
  if (thinkingLevel === "xHigh" || thinkingLevel === "Max") levelKey = "xHigh";
1061
1062
  const thinkingConfig = thinking_prompts_default[levelKey] || thinking_prompts_default["Medium"];
1062
1063
  const osDetected = process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux";
1063
- const nameStr = profile.name && profile.name?.length > 0 ? `User Name: ${profile.name}
1064
- ` : "";
1065
- const nicknameStr = profile.nickname && profile.nickname?.length > 0 ? `User Nickname: ${profile.nickname}
1066
- ` : "";
1067
1064
  const userInstrStr = profile.instructions && profile.instructions?.length > 0 ? `User Instructions: ${profile.instructions}
1065
+
1068
1066
  ` : "";
1067
+ const nicknameStr = profile.nickname && profile.nickname?.length > 0 ? `User Nickname: ${profile.nickname}
1068
+ ${userInstrStr.length ? "" : "\n"}` : "";
1069
+ const nameStr = profile.name && profile.name?.length > 0 ? `User Name: ${profile.name}
1070
+ ${nicknameStr.length || userInstrStr.length ? "" : "\n"}` : "";
1069
1071
  const cwdStr = process.cwd();
1070
1072
  const isSystemDir = (() => {
1071
1073
  const cwd = process.cwd().toLowerCase();
@@ -1092,12 +1094,11 @@ ${parts.join("\n\n")}
1092
1094
  -- PROJECT CONTEXT (Source of Truth) --
1093
1095
  ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
1094
1096
  Check these first; these files > training data for project consistency. Safety rules apply` : "";
1095
- return `${nameStr}${nicknameStr}${userInstrStr}
1096
- [SYSTEM (OVERRIDES EVERYTHING)]
1097
+ return `${nameStr}${nicknameStr}${userInstrStr}[SYSTEM (OVERRIDES EVERYTHING)]
1097
1098
  Identity: Flux Flow (by Kushal Roy Chowdhury). Sassy, Friendly, Humorous, CLI Agent. No flirting ${mode === "Flux" ? "" : ""}
1098
1099
  Mode: ${mode}${thinkingLevel !== "Fast" ? "(Thinking Mode)" : ""}. ${mode === "Flux" ? "Goal-oriented, Logical" : "Conversational & UX-focused"}
1099
1100
  CWD: ${cwdStr}.${isSystemDir ? " [PROTECTED: ASK BEFORE MODIFYING]" : ""} OS: ${osDetected}${osDetected === "Windows" && mode === "Flux" ? ". PS via CMD" : ""}
1100
- High Priority: [SYSTEM], [STEERING HINT]
1101
+ High Priority: [SYSTEM], [STEERING HINT].
1101
1102
 
1102
1103
  -- THINKING RULES --
1103
1104
  ${thinkingConfig}
@@ -1117,6 +1118,7 @@ ${projectContextBlock}
1117
1118
  -- SECURITY RULES --
1118
1119
  - EXTERNAL ACCESS: ${systemSettings.allowExternalAccess ? "ENABLED" : "RESTRICTED CWD only"}
1119
1120
  - Sensitive files? Ask before Read
1121
+ [SYSTEM] >>> [USER]
1120
1122
 
1121
1123
  -- FORMATTING --
1122
1124
  - Clean, concise responses
@@ -1130,15 +1132,11 @@ ${projectContextBlock}
1130
1132
  [/SYSTEM]`.trim();
1131
1133
  };
1132
1134
  getJanitorInstruction = (userMemories = "", isMemoryEnabled = true, needTitle = true) => {
1133
- return `
1134
- ${userMemories ? `
1135
-
1136
- -- CURRENT PERSISTENT USER MEMORIES --
1135
+ return `${userMemories ? `-- CURRENT SAVED USER MEMORIES --
1137
1136
  ${userMemories}
1138
1137
  -------------------------------------------------
1139
- ` : ""}
1140
1138
 
1141
- === START SYSTEM PROMPT (STRICT HEADLESS LOGIC WORKER: ZERO USER-FACING TEXT POLICY, STRICTLY FOLLOW) ===
1139
+ ` : ""}=== START SYSTEM PROMPT (STRICT HEADLESS LOGIC WORKER: ZERO USER-FACING TEXT POLICY, STRICTLY FOLLOW) ===
1142
1140
  YOU ARE A SILENT BACKGROUND SYSTEM PROCESS. YOU HAVE NO MOUTH. YOUR ONLY OUTPUT MEDIUM IS VALID TOOL CALLS.
1143
1141
  [CRITICAL RULES]
1144
1142
  1. OUTPUT ONLY '[tool:functions.xxx(args)]' CALLS (BRACKET WRAP IS MANDATORY).
@@ -3531,7 +3529,7 @@ var init_ai = __esm({
3531
3529
  const isMemoryEnabled = systemSettings?.memory !== false;
3532
3530
  const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
3533
3531
  const janitorUserMemories = persistentStorage.map((m) => `- [${m.id}]: ${m.memory}`).join("\n");
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) => {
3532
+ 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(-14).map((msg) => {
3535
3533
  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
3534
  return `[METADATA (PRIORITY: DYNAMIC)] Time: ${p1.replace(/:\d{2}/g, "")}`;
3537
3535
  }).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();
@@ -3571,7 +3569,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3571
3569
  const MAX_JANITOR_RETRIES = 12;
3572
3570
  while (attempts <= MAX_JANITOR_RETRIES) {
3573
3571
  if (process.stdout.isTTY) {
3574
- process.stdout.write(`\x1B]0;Retrying Memory (${attempts + 1})...\x07`);
3572
+ process.stdout.write(`\x1B]0;Retrying Finalizing... (${attempts + 1})...\x07`);
3575
3573
  }
3576
3574
  try {
3577
3575
  if (!await checkQuota("background", settings)) {
@@ -3654,7 +3652,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3654
3652
  attempts++;
3655
3653
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
3656
3654
  if (process.stdout.isTTY) {
3657
- process.stdout.write(`\x1B]0;Memory Error\x07`);
3655
+ process.stdout.write(`\x1B]0;Finalizing Error\x07`);
3658
3656
  }
3659
3657
  await new Promise((resolve) => setTimeout(resolve, 1e3));
3660
3658
  const janitorErrDir = path14.join(LOGS_DIR, "janitor");
@@ -3675,7 +3673,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3675
3673
  `);
3676
3674
  if (attempts >= MAX_JANITOR_RETRIES) {
3677
3675
  if (process.stdout.isTTY) {
3678
- process.stdout.write(`\x1B]0;Memory Error\x07`);
3676
+ process.stdout.write(`\x1B]0;Finalizing Error\x07`);
3679
3677
  }
3680
3678
  await new Promise((resolve) => setTimeout(resolve, 3e3));
3681
3679
  }
@@ -5458,6 +5456,7 @@ function App({ args = [] }) {
5458
5456
  { cmd: "/clear", desc: "Clear terminal screen" },
5459
5457
  { cmd: "/resume", desc: "Load previous session" },
5460
5458
  { cmd: "/save", desc: "Force save current chat" },
5459
+ { cmd: "/export", desc: "Export current chat in a .txt file" },
5461
5460
  { cmd: "/chats", desc: "List all chat sessions" },
5462
5461
  {
5463
5462
  cmd: "/image",
@@ -5872,6 +5871,71 @@ ${hintText}`, color: "magenta" }];
5872
5871
  });
5873
5872
  break;
5874
5873
  }
5874
+ case "/export": {
5875
+ const exportFile = `export-fluxflow-${chatId}.txt`;
5876
+ const exportPath = path15.join(process.cwd(), exportFile);
5877
+ const exportLines = [];
5878
+ let insideAgentBlock = false;
5879
+ for (let i = 0; i < messages.length; i++) {
5880
+ const msg = messages[i];
5881
+ if (!msg) continue;
5882
+ if (msg.role === "system" || msg.isMeta || msg.isLogo || String(msg.id).startsWith("welcome")) {
5883
+ continue;
5884
+ }
5885
+ if (msg.role === "user") {
5886
+ let cleanUserText = msg.text || "";
5887
+ cleanUserText = cleanUserText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
5888
+ if (exportLines.length > 0) {
5889
+ exportLines.push("");
5890
+ }
5891
+ exportLines.push("[USER]");
5892
+ exportLines.push(cleanUserText);
5893
+ insideAgentBlock = false;
5894
+ } else if (msg.role === "think") {
5895
+ if (!insideAgentBlock) {
5896
+ exportLines.push("");
5897
+ exportLines.push("[AGENT]");
5898
+ insideAgentBlock = true;
5899
+ }
5900
+ const cleanThinkText = (msg.text || "").replace(/\[turn:\s*continue\]/gi, "").replace(/\[turn:\s*finish\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").trim();
5901
+ if (cleanThinkText) {
5902
+ exportLines.push("[thoughts]");
5903
+ exportLines.push(cleanThinkText);
5904
+ }
5905
+ } else if (msg.role === "agent") {
5906
+ if (!insideAgentBlock) {
5907
+ exportLines.push("");
5908
+ exportLines.push("[AGENT]");
5909
+ insideAgentBlock = true;
5910
+ }
5911
+ const blocks = parseAgentText(msg.text || "");
5912
+ for (const block of blocks) {
5913
+ if (block.type === "output") {
5914
+ const cleanContent = block.content.replace(/\[turn:\s*continue\]/gi, "").replace(/\[turn:\s*finish\]/gi, "").replace(/\[TOOL RESULTS\]/gi, "").trim();
5915
+ if (cleanContent) {
5916
+ exportLines.push("[output]");
5917
+ exportLines.push(cleanContent);
5918
+ }
5919
+ } else if (block.type === "tool") {
5920
+ exportLines.push("[tool]");
5921
+ exportLines.push(`${block.toolName} ${block.args}`);
5922
+ }
5923
+ }
5924
+ }
5925
+ }
5926
+ const fileContent = exportLines.join("\n");
5927
+ fs17.writeFileSync(exportPath, fileContent, "utf8");
5928
+ setMessages((prev) => {
5929
+ setCompletedIndex(prev.length + 1);
5930
+ return [...prev, {
5931
+ id: Date.now(),
5932
+ role: "system",
5933
+ text: `\u{1F4E4} [EXPORT] Chat exported successfully to "${exportFile}"`,
5934
+ isMeta: true
5935
+ }];
5936
+ });
5937
+ break;
5938
+ }
5875
5939
  case "/chats": {
5876
5940
  const run = async () => {
5877
5941
  const history = await loadHistory();
@@ -6963,7 +7027,7 @@ Selection: ${val}`,
6963
7027
  );
6964
7028
  })()));
6965
7029
  }
6966
- var SESSION_START_TIME, CHANGELOG_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, FLUX_LOGO;
7030
+ var SESSION_START_TIME, CHANGELOG_URL, packageJsonPath, packageJson, versionFluxflow, updatedOn, ResolutionModal, FLUX_LOGO, parseAgentText;
6967
7031
  var init_app = __esm({
6968
7032
  "src/app.jsx"() {
6969
7033
  init_ChatLayout();
@@ -7014,6 +7078,71 @@ var init_app = __esm({
7014
7078
  \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2554\u255D \u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2554\u2588\u2588\u2588\u2554\u255D
7015
7079
  \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u255D\u255A\u2550\u2550\u255D`
7016
7080
  );
7081
+ parseAgentText = (text) => {
7082
+ const blocks = [];
7083
+ const toolRegex = /\[\s*tool:functions\.([a-z0-9_]+)\s*\(/gi;
7084
+ let lastIdx = 0;
7085
+ let match;
7086
+ while ((match = toolRegex.exec(text)) !== null) {
7087
+ const toolName = match[1];
7088
+ const startIdx = match.index + match[0].length - 1;
7089
+ let balance = 0;
7090
+ let inString = null;
7091
+ let isEscaped = false;
7092
+ let endIdx = -1;
7093
+ let closingParenIdx = -1;
7094
+ for (let i = startIdx; i < text.length; i++) {
7095
+ const char = text[i];
7096
+ if (!inString && (char === '"' || char === "'" || char === "`")) {
7097
+ inString = char;
7098
+ isEscaped = false;
7099
+ } else if (inString && char === inString && !isEscaped) {
7100
+ inString = null;
7101
+ }
7102
+ if (!inString) {
7103
+ if (char === "(") balance++;
7104
+ else if (char === ")") balance--;
7105
+ if (balance === 0) {
7106
+ closingParenIdx = i;
7107
+ let j = i + 1;
7108
+ while (j < text.length && /\s/.test(text[j])) j++;
7109
+ if (j < text.length && text[j] === "]") {
7110
+ endIdx = j;
7111
+ break;
7112
+ }
7113
+ }
7114
+ }
7115
+ if (char === "\\") {
7116
+ isEscaped = !isEscaped;
7117
+ } else {
7118
+ isEscaped = false;
7119
+ }
7120
+ }
7121
+ if (endIdx !== -1) {
7122
+ const beforeText = text.substring(lastIdx, match.index);
7123
+ if (beforeText.trim()) {
7124
+ blocks.push({ type: "output", content: beforeText });
7125
+ }
7126
+ const finalArgsText = text.substring(startIdx + 1, closingParenIdx);
7127
+ blocks.push({
7128
+ type: "tool",
7129
+ toolName: toolName.trim(),
7130
+ args: finalArgsText.trim()
7131
+ });
7132
+ lastIdx = endIdx + 1;
7133
+ toolRegex.lastIndex = lastIdx;
7134
+ } else {
7135
+ break;
7136
+ }
7137
+ }
7138
+ if (lastIdx < text.length) {
7139
+ const remainingText = text.substring(lastIdx);
7140
+ if (remainingText.trim()) {
7141
+ blocks.push({ type: "output", content: remainingText });
7142
+ }
7143
+ }
7144
+ return blocks;
7145
+ };
7017
7146
  }
7018
7147
  });
7019
7148
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "1.12.6",
4
- "date": "2026-05-22",
3
+ "version": "1.12.8",
4
+ "date": "2026-05-23",
5
5
  "description": "A high-fidelity agentic terminal assistant for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",