fluxflow-cli 3.5.1 → 3.6.0

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 CHANGED
@@ -6118,7 +6118,7 @@ function SettingsMenu({
6118
6118
  { label: "Auto Approve Commands", value: "autoApprove", status: truncateCSV(systemSettings.autoApproveCommands), section: "Sandbox" },
6119
6119
  { label: "Auto Disapprove Commands", value: "autoDisallow", status: truncateCSV(systemSettings.autoDisallowCommands), section: "Sandbox" },
6120
6120
  { label: "Auto Approve Git Commits", value: "autoApproveGit", status: systemSettings.autoApproveGit ? "ON" : "OFF", section: "Sandbox" },
6121
- { label: "Advanced Rollback [EXPERIMENTAL]", value: "advanceRollback", status: systemSettings.advanceRollback ? "ON" : "OFF", section: "Other" },
6121
+ { label: "Advanced Recovery [EXPERIMENTAL]", value: "advanceRollback", status: systemSettings.advanceRollback ? "ON" : "OFF", section: "Other" },
6122
6122
  { label: "Auto-Delete History", value: "autoDelete", status: systemSettings.autoDeleteHistory || "30d", section: "Other" },
6123
6123
  { label: "Save AppData Externally", value: "externalData", status: systemSettings.useExternalData ? "ON" : "OFF", section: "Other" }
6124
6124
  ];
@@ -9122,12 +9122,19 @@ var init_search_keyword = __esm({
9122
9122
  const regexExplicitlyFalse = regex === false || regex === "false" || regex === 0 || regex === "0" || regex === "no";
9123
9123
  let matchRegex = toBool(regex);
9124
9124
  let matchSubstring = !matchRegex && toBool(subString);
9125
- const hasRegexIndicators = /[|]/.test(keyword) || /\\([*+?{}()|[\]\^$])/.test(keyword);
9126
- let isAutoRegex = false;
9125
+ const hasRegexIndicators = /[|]/.test(keyword) || /\\([*+?{}()|[\]\^$])/.test(keyword) || (() => {
9126
+ const stripped = keyword.replace(/\\./g, "");
9127
+ return /[*+?{}()|]/.test(stripped) || /\[.*?\]/.test(stripped) || /^\^/.test(stripped) || /\$/.test(stripped);
9128
+ })();
9129
+ let isAutoRegex = true;
9127
9130
  if (!matchRegex && !regexExplicitlyFalse && hasRegexIndicators) {
9128
9131
  matchRegex = true;
9129
9132
  isAutoRegex = true;
9130
9133
  }
9134
+ if (regexExplicitlyFalse) {
9135
+ matchRegex = false;
9136
+ isAutoRegex = false;
9137
+ }
9131
9138
  let regexPattern;
9132
9139
  let wordRegex;
9133
9140
  if (matchRegex) {
@@ -10565,6 +10572,23 @@ var init_advanceRevert = __esm({
10565
10572
  throw new Error(`Rollback failed: ${err.message}`);
10566
10573
  }
10567
10574
  },
10575
+ async getLatestFileChanges(chatId) {
10576
+ try {
10577
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10578
+ const session = ledger[chatId];
10579
+ if (!session || !session.checkpoints || session.checkpoints.length === 0) {
10580
+ return { newFiles: [], modifiedFiles: [], deletedFiles: [] };
10581
+ }
10582
+ const lastCp = session.checkpoints[session.checkpoints.length - 1];
10583
+ return {
10584
+ newFiles: lastCp.newFiles || [],
10585
+ modifiedFiles: lastCp.modifiedFiles || [],
10586
+ deletedFiles: lastCp.deletedFiles || []
10587
+ };
10588
+ } catch (err) {
10589
+ return { newFiles: [], modifiedFiles: [], deletedFiles: [] };
10590
+ }
10591
+ },
10568
10592
  async cleanup(chatId) {
10569
10593
  try {
10570
10594
  const snapshotsDir = path21.join(DATA_DIR, "snapshots", chatId);
@@ -12628,6 +12652,8 @@ Provide a consolidated summary of the entire session.`;
12628
12652
  const needTitle = isFirstPrompt || hasTitleSignal;
12629
12653
  let agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
12630
12654
  agentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
12655
+ yield { type: "status", content: "[start]" };
12656
+ yield { type: "status", content: "Gathering Context" };
12631
12657
  await RevertManager.startTransaction(chatId, agentText);
12632
12658
  if (systemSettings?.advanceRollback) {
12633
12659
  await AdvanceRevertManager.takeInitialSnapshot(chatId);
@@ -12935,8 +12961,6 @@ Provide a consolidated summary of the entire session.`;
12935
12961
  });
12936
12962
  return result;
12937
12963
  };
12938
- yield { type: "status", content: "[start]" };
12939
- yield { type: "status", content: "Gathering Context" };
12940
12964
  const totalFolders = countFolders(process.cwd());
12941
12965
  let dynamicMaxDepth = 12;
12942
12966
  if (totalFolders > 4096) dynamicMaxDepth = 1;
@@ -13442,6 +13466,23 @@ ${ideErr} [/ERROR]`;
13442
13466
  lastUserMsg.parts[0].text += jitInstruction;
13443
13467
  }
13444
13468
  }
13469
+ if (systemSettings?.advanceRollback && lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
13470
+ try {
13471
+ const fileChanges = await AdvanceRevertManager.getLatestFileChanges(chatId);
13472
+ if (fileChanges && (fileChanges.newFiles.length > 0 || fileChanges.modifiedFiles.length > 0 || fileChanges.deletedFiles.length > 0)) {
13473
+ let changesStr = "\n[SYSTEM] File Changes:\n";
13474
+ for (const f of fileChanges.newFiles) changesStr += `* ${f} (created)
13475
+ `;
13476
+ for (const f of fileChanges.modifiedFiles) changesStr += `* ${f} (modified)
13477
+ `;
13478
+ for (const f of fileChanges.deletedFiles) changesStr += `* ${f} (deleted)
13479
+ `;
13480
+ changesStr += "[/SYSTEM]";
13481
+ lastUserMsg.parts[0].text += changesStr;
13482
+ }
13483
+ } catch (err) {
13484
+ }
13485
+ }
13445
13486
  if (isGemma) {
13446
13487
  const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.98 : 0.8));
13447
13488
  const currentStep = loop + 1;
@@ -15203,6 +15244,29 @@ Error Log can be found in ${path22.join(LOGS_DIR, "agent", "error.log")}`);
15203
15244
  } else {
15204
15245
  modifiedHistory.push({ role: "agent", text: cleanedFullResponse });
15205
15246
  }
15247
+ modifiedHistory.forEach((msg) => {
15248
+ if (msg.role === "user" && msg.text) {
15249
+ msg.text = msg.text.replace(/\n\[COMPILE ERROR\][\s\S]*?\[\/ERROR\]/g, "");
15250
+ msg.text = msg.text.replaceAll(`
15251
+
15252
+ [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
15253
+ `, "").replaceAll(`[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY
15254
+ **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15255
+ `, "").replaceAll(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15256
+ `, "").replaceAll(
15257
+ /\n\[SYSTEM\] WARNING, Turn Limit Impending: Step \d+\/\d+\. Wrap up quickly\/prompt user to continue & use \[\[END\]\] quickly\. \[\/SYSTEM\]/g,
15258
+ ""
15259
+ );
15260
+ msg.text = msg.text.replaceAll(/\n\[SYSTEM\] File Changes:\n(?:\* .+ \(created|modified|deleted\)\n)*\[\/SYSTEM\]/g, "");
15261
+ if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
15262
+ const jitInstructionFast = `
15263
+ [SYSTEM] Tool result received. Analyze output and proceed with your turn [/SYSTEM]`;
15264
+ const jitInstructionThinking = `
15265
+ [SYSTEM] Tool result received. Analyze output and proceed with your turn. **STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]`;
15266
+ msg.text = msg.text.replaceAll(jitInstructionThinking, "").replaceAll(jitInstructionFast, "").trim();
15267
+ }
15268
+ }
15269
+ });
15206
15270
  yield { type: "status", content: "[end]" };
15207
15271
  }
15208
15272
  if (isActuallyFinished) break;
@@ -15236,28 +15300,6 @@ Error Log can be found in ${path22.join(LOGS_DIR, "agent", "error.log")}`);
15236
15300
  }
15237
15301
  wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
15238
15302
  }
15239
- modifiedHistory.forEach((msg) => {
15240
- if (msg.role === "user" && msg.text) {
15241
- msg.text = msg.text.replace(/\n\[COMPILE ERROR\][\s\S]*?\[\/ERROR\]/g, "");
15242
- msg.text = msg.text.replace(`
15243
-
15244
- [SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY [/SYSTEM]
15245
- `, "").replace(`[SYSTEM] USER QUESTION. RESOLVE THIS SPECIFIC QUERY WITHIN '[ANSWER] ... [/ANSWER]' CONCISELY, NATURALLY
15246
- **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15247
- `, "").replace(`[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS HIGH PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]
15248
- `, "").replaceAll(
15249
- /\n\[SYSTEM\] WARNING, Turn Limit Impending: Step \d+\/\d+\. Wrap up quickly\/prompt user to continue & use \[\[END\]\] quickly\. \[\/SYSTEM\]/g,
15250
- ""
15251
- );
15252
- if (modelName && modelName.toLowerCase().startsWith("gemma") && aiProvider === "Google" && msg.text.startsWith("[TOOL RESULT]")) {
15253
- const jitInstructionFast = `
15254
- [SYSTEM] Tool result received. Analyze output and proceed with your turn [/SYSTEM]`;
15255
- const jitInstructionThinking = `
15256
- [SYSTEM] Tool result received. Analyze output and proceed with your turn. **STRICTLY MAINTAIN THINKING POLICY. DO NOT START A RESPONSE WITHOUT <think> ... </think>** [/SYSTEM]`;
15257
- msg.text = msg.text.replace(jitInstructionThinking, "").replace(jitInstructionFast, "").trim();
15258
- }
15259
- }
15260
- });
15261
15303
  } catch (err) {
15262
15304
  const errLog = err instanceof Error ? (() => {
15263
15305
  try {
@@ -20592,7 +20634,7 @@ Selection: ${val}`,
20592
20634
  width: "100%",
20593
20635
  marginBottom: 1
20594
20636
  },
20595
- /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use \\'#Lstart-Lend\\' to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20637
+ /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") || suggestions[0]?.cmd?.startsWith("\\@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use #Lstart-Lend to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20596
20638
  let url = "https://aistudio.google.com/billing";
20597
20639
  let label = "billing";
20598
20640
  if (aiProvider === "DeepSeek") {
package/model_config.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 0,
3
- "release": 20260720,
3
+ "release": 20260721,
4
4
  "fallbacks": {
5
5
  "janitor_default": "gemini-3.1-flash-lite",
6
6
  "janitor_attempts_fallback": "gemma-4-26b-a4b-it",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.5.1",
4
- "date": "2026-07-20",
3
+ "version": "3.6.0",
4
+ "date": "2026-07-21",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [
7
7
  "ai",