fluxflow-cli 3.0.22 → 3.1.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.
Files changed (2) hide show
  1. package/dist/fluxflow.js +456 -127
  2. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -42,6 +42,7 @@ __export(paths_exports, {
42
42
  FLUXFLOW_DIR: () => FLUXFLOW_DIR,
43
43
  HISTORY_DIR: () => HISTORY_DIR,
44
44
  HISTORY_FILE: () => HISTORY_FILE,
45
+ LEDGER_ADVANCE_FILE: () => LEDGER_ADVANCE_FILE,
45
46
  LEDGER_FILE: () => LEDGER_FILE,
46
47
  LOGS_DIR: () => LOGS_DIR,
47
48
  MEMORIES_FILE: () => MEMORIES_FILE,
@@ -57,7 +58,7 @@ import os from "os";
57
58
  import path from "path";
58
59
  import fs from "fs";
59
60
  import crypto from "crypto";
60
- var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
61
+ var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, HISTORY_DIR, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE, LEDGER_ADVANCE_FILE, ACTIVE_TX_FILE, PATHS_FILE, CONTEXT_FILE, PARSER_DIR;
61
62
  var init_paths = __esm({
62
63
  "src/utils/paths.js"() {
63
64
  FLUXFLOW_DIR = path.join(os.homedir(), ".fluxflow");
@@ -101,6 +102,7 @@ var init_paths = __esm({
101
102
  TEMP_MEM_CHAT_FILE = path.join(SECRET_DIR, "temp-memory-chat.json");
102
103
  BACKUPS_DIR = path.join(DATA_DIR, "backups");
103
104
  LEDGER_FILE = path.join(SECRET_DIR, "ledger.json");
105
+ LEDGER_ADVANCE_FILE = path.join(SECRET_DIR, "ledgerAdvance.json");
104
106
  ACTIVE_TX_FILE = path.join(SECRET_DIR, "active_tx.json");
105
107
  PATHS_FILE = path.join(SECRET_DIR, "path.json");
106
108
  CONTEXT_FILE = path.join(SECRET_DIR, "context.json");
@@ -136,6 +138,7 @@ var init_crypto = __esm({
136
138
  return iv.toString("hex") + ":" + encrypted;
137
139
  };
138
140
  decryptAes = (encryptedText) => {
141
+ if (bypass) return encryptedText;
139
142
  const parts = encryptedText.split(":");
140
143
  if (parts.length !== 2) {
141
144
  throw new Error("Invalid AES format");
@@ -318,6 +321,7 @@ var init_settings = __esm({
318
321
  compression: 0,
319
322
  autoExec: false,
320
323
  allowExternalAccess: false,
324
+ advanceRollback: false,
321
325
  autoDeleteHistory: "7d",
322
326
  useExternalData: false,
323
327
  externalDataPath: ""
@@ -5162,7 +5166,7 @@ var init_main_tools = __esm({
5162
5166
  }
5163
5167
  return _isPsAvailable;
5164
5168
  };
5165
- TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider) => `
5169
+ TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider, advanceRollback = false) => `
5166
5170
  -- TOOL DEFINITIONS --
5167
5171
  Internal tools. **MUST use the EXACT syntax** [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
5168
5172
 
@@ -5186,7 +5190,10 @@ ${mode === "Flux" ? `- WORKSPACE TOOLS (path = relative to CWD & WILL BE FIRST A
5186
5190
  7. [tool:functions.Run(command="...")]. Runs ${osDetected === "Windows" ? isPsAvailable() ? `WINDOWS POWERSHELL ONLY` : `WINDOWS CMD ONLY` : `BASH`} command. Destructive/Irreversible ops \u2192 Ask user
5187
5191
  8. [tool:functions.Todo(method="create/append/get", tasks=[ARRAY OF STRINGS], markDone=[ARRAY OF TASK STRINGS])]. Task List, NO Markdown IN ARRAY. USAGE: ANALYZE USER REQUEST **IF** MULTIPLE TASK \u2192 BREAK DOWN TASK \u2192 CREATE TODO **BEFORE** DIVING IN. 'tasks' & 'markDone' OPTIONAL PARAMETERS WITH method 'get'. USE 'get' method WITH 'markDone' to mark task completed. **EVERY TURN UPDATE POLICY**
5188
5192
  9. [tool:functions.Await(time="seconds")]. For waiting without exiting agent loop, 15s - 180s
5189
-
5193
+ ${advanceRollback ? `
5194
+ - EMERGENCY SAFETY TOOLS -
5195
+ 1. [tool:functions.EmergencyRollback(method="getCheckpoint/forceRevert", id="...")]. Rollback workspace during execution to a specific turn checkpoint. Usage: ONLY in catastrophic codebase error/deletions. Verify nothing catastrophic happened in codebase before ending agent loop. 'id' not needed with getCheckPoint
5196
+ ` : ""}
5190
5197
  -- SUB AGENTS DEFINITIONS --
5191
5198
  **PROACTIVE USE OF SUB AGENTS HIGHLY RECOMMENDED, PREFER USING FOR ALL TASK WHERE PLAUSIBLE & BENEFICIAL, EVEN WITHOUT EXPLICIT USER NUDGE**
5192
5199
 
@@ -5944,6 +5951,7 @@ function SettingsMenu({
5944
5951
  { label: "Auto Approve Commands", value: "autoApprove", status: truncateCSV(systemSettings.autoApproveCommands), section: "Sandbox" },
5945
5952
  { label: "Auto Disapprove Commands", value: "autoDisallow", status: truncateCSV(systemSettings.autoDisallowCommands), section: "Sandbox" },
5946
5953
  { label: "Auto Approve Git Commits", value: "autoApproveGit", status: systemSettings.autoApproveGit ? "ON" : "OFF", section: "Sandbox" },
5954
+ { label: "Advanced Rollback [EXPERIMENTAL]", value: "advanceRollback", status: systemSettings.advanceRollback ? "ON" : "OFF", section: "Other" },
5947
5955
  { label: "Auto-Delete History", value: "autoDelete", status: systemSettings.autoDeleteHistory || "30d", section: "Other" },
5948
5956
  { label: "Save AppData Externally", value: "externalData", status: systemSettings.useExternalData ? "ON" : "OFF", section: "Other" }
5949
5957
  ];
@@ -6075,6 +6083,16 @@ function SettingsMenu({
6075
6083
  setActiveView("apiTier");
6076
6084
  } else if (item.value === "aiProvider") {
6077
6085
  setActiveView("selectProvider");
6086
+ } else if (item.value === "advanceRollback") {
6087
+ if (!systemSettings.advanceRollback) {
6088
+ setActiveView("advanceRollbackDanger");
6089
+ } else {
6090
+ setSystemSettings((s) => {
6091
+ const newSysSettings = { ...s, advanceRollback: false };
6092
+ saveSettings2({ systemSettings: newSysSettings, apiTier, quotas });
6093
+ return newSysSettings;
6094
+ });
6095
+ }
6078
6096
  } else if (item.value === "autoDelete") {
6079
6097
  const options = ["1d", "7d", "30d"];
6080
6098
  const currentIndex = options.indexOf(systemSettings.autoDeleteHistory || "30d");
@@ -6544,7 +6562,7 @@ ${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" && !isGemini ? `
6544
6562
  CRITICAL THINKING POLICY
6545
6563
  - ALWAYS use <think> ... </think> before responding, even with simple queries/greetings
6546
6564
  ` : ""}` : `${thinkingConfig}`}
6547
- ${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider)}
6565
+ ${TOOL_PROTOCOL(mode, osDetected, aiProvider.toLowerCase() === "deepseek" ? false : isMultiModal, aiProvider, systemSettings?.advanceRollback)}
6548
6566
  ${projectContextBlock}
6549
6567
  -- MEMORY RULES --
6550
6568
  - Memory: ${isMemoryEnabled ? "Subtly Personalize. Auto Saves" : "OFF. Decline Remembering Memories"}
@@ -10044,6 +10062,281 @@ var init_await = __esm({
10044
10062
  }
10045
10063
  });
10046
10064
 
10065
+ // src/utils/advanceRevert.js
10066
+ import fs21 from "fs-extra";
10067
+ import path20 from "path";
10068
+ async function scanWorkspace(dir, baseDir = dir) {
10069
+ const manifest = {};
10070
+ const entries = await fs21.readdir(dir, { withFileTypes: true }).catch(() => []);
10071
+ for (const entry of entries) {
10072
+ if (JUNK_DIRECTORIES.includes(entry.name)) continue;
10073
+ const fullPath = path20.join(dir, entry.name);
10074
+ const relPath = path20.relative(baseDir, fullPath).replace(/\\/g, "/");
10075
+ if (entry.isDirectory()) {
10076
+ const sub = await scanWorkspace(fullPath, baseDir);
10077
+ Object.assign(manifest, sub);
10078
+ } else {
10079
+ const stats = await fs21.stat(fullPath).catch(() => null);
10080
+ if (stats) {
10081
+ manifest[relPath] = {
10082
+ size: stats.size,
10083
+ mtime: stats.mtimeMs
10084
+ };
10085
+ }
10086
+ }
10087
+ }
10088
+ return manifest;
10089
+ }
10090
+ async function copyWorkspaceFiles(destDir, manifest) {
10091
+ await fs21.ensureDir(destDir);
10092
+ for (const relPath of Object.keys(manifest)) {
10093
+ const srcPath = path20.join(process.cwd(), relPath);
10094
+ const destPath = path20.join(destDir, relPath);
10095
+ await fs21.ensureDir(path20.dirname(destPath));
10096
+ await fs21.copyFile(srcPath, destPath).catch(() => {
10097
+ });
10098
+ }
10099
+ }
10100
+ async function restoreSnapshotDir(srcDir, destDir) {
10101
+ if (!await fs21.pathExists(srcDir)) return;
10102
+ const entries = await fs21.readdir(srcDir, { withFileTypes: true }).catch(() => []);
10103
+ for (const entry of entries) {
10104
+ const srcPath = path20.join(srcDir, entry.name);
10105
+ const destPath = path20.join(destDir, entry.name);
10106
+ if (entry.isDirectory()) {
10107
+ await restoreSnapshotDir(srcPath, destPath);
10108
+ } else {
10109
+ if (await fs21.pathExists(destPath)) {
10110
+ await fs21.chmod(destPath, 438).catch(() => {
10111
+ });
10112
+ }
10113
+ await fs21.ensureDir(path20.dirname(destPath));
10114
+ await fs21.copyFile(srcPath, destPath).catch(() => {
10115
+ });
10116
+ await fs21.chmod(destPath, 438).catch(() => {
10117
+ });
10118
+ }
10119
+ }
10120
+ }
10121
+ var JUNK_DIRECTORIES, AdvanceRevertManager;
10122
+ var init_advanceRevert = __esm({
10123
+ "src/utils/advanceRevert.js"() {
10124
+ init_paths();
10125
+ init_crypto();
10126
+ JUNK_DIRECTORIES = [
10127
+ "node_modules",
10128
+ "dist",
10129
+ "bin",
10130
+ "logs",
10131
+ ".git",
10132
+ ".fluxflow",
10133
+ "secret",
10134
+ ".gemini",
10135
+ ".agents",
10136
+ "tmp",
10137
+ "temp",
10138
+ "build",
10139
+ "out",
10140
+ "snapshots"
10141
+ ];
10142
+ AdvanceRevertManager = {
10143
+ async takeInitialSnapshot(chatId) {
10144
+ try {
10145
+ const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10146
+ await fs21.remove(snapshotsDir).catch(() => {
10147
+ });
10148
+ await fs21.ensureDir(snapshotsDir);
10149
+ const manifest = await scanWorkspace(process.cwd());
10150
+ await copyWorkspaceFiles(path20.join(snapshotsDir, "initial"), manifest);
10151
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10152
+ ledger[chatId] = {
10153
+ initialManifest: manifest,
10154
+ currentManifest: manifest,
10155
+ checkpoints: [
10156
+ {
10157
+ id: "initial",
10158
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10159
+ newFiles: [],
10160
+ modifiedFiles: [],
10161
+ deletedFiles: [],
10162
+ toolsUsed: []
10163
+ }
10164
+ ]
10165
+ };
10166
+ writeEncryptedJson(LEDGER_ADVANCE_FILE, ledger);
10167
+ } catch (err) {
10168
+ }
10169
+ },
10170
+ async recordTurnDelta(chatId, turnNumber, toolsUsed = []) {
10171
+ try {
10172
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10173
+ const session = ledger[chatId];
10174
+ if (!session) return;
10175
+ const previousManifest = session.currentManifest || session.initialManifest;
10176
+ const currentManifest = await scanWorkspace(process.cwd());
10177
+ const newFiles = [];
10178
+ const modifiedFiles = [];
10179
+ const deletedFiles = [];
10180
+ for (const [relPath, info] of Object.entries(currentManifest)) {
10181
+ const prev = previousManifest[relPath];
10182
+ if (!prev) {
10183
+ newFiles.push(relPath);
10184
+ } else if (prev.size !== info.size || prev.mtime !== info.mtime) {
10185
+ modifiedFiles.push(relPath);
10186
+ }
10187
+ }
10188
+ for (const relPath of Object.keys(previousManifest)) {
10189
+ if (!currentManifest[relPath]) {
10190
+ deletedFiles.push(relPath);
10191
+ }
10192
+ }
10193
+ const changedFiles = [...newFiles, ...modifiedFiles];
10194
+ if (changedFiles.length > 0 || deletedFiles.length > 0) {
10195
+ const deltaManifest = {};
10196
+ for (const file of changedFiles) {
10197
+ deltaManifest[file] = currentManifest[file];
10198
+ }
10199
+ const turnDir = path20.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
10200
+ await copyWorkspaceFiles(turnDir, deltaManifest);
10201
+ }
10202
+ session.checkpoints.push({
10203
+ id: `turn_${turnNumber}`,
10204
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10205
+ newFiles,
10206
+ modifiedFiles,
10207
+ deletedFiles,
10208
+ toolsUsed
10209
+ });
10210
+ session.currentManifest = currentManifest;
10211
+ writeEncryptedJson(LEDGER_ADVANCE_FILE, ledger);
10212
+ } catch (err) {
10213
+ }
10214
+ },
10215
+ async getCheckpoints(chatId) {
10216
+ try {
10217
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10218
+ const session = ledger[chatId];
10219
+ if (!session) return [];
10220
+ return session.checkpoints || [];
10221
+ } catch (err) {
10222
+ return [];
10223
+ }
10224
+ },
10225
+ async rollbackToCheckpoint(chatId, checkpointId) {
10226
+ try {
10227
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10228
+ const session = ledger[chatId];
10229
+ if (!session) throw new Error("No session active for Advance Rollback.");
10230
+ const checkpoints = session.checkpoints || [];
10231
+ const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
10232
+ if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
10233
+ const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10234
+ const currentFiles = await scanWorkspace(process.cwd());
10235
+ for (const relPath of Object.keys(currentFiles)) {
10236
+ const fullPath = path20.join(process.cwd(), relPath);
10237
+ await fs21.chmod(fullPath, 438).catch(() => {
10238
+ });
10239
+ await fs21.remove(fullPath).catch(() => {
10240
+ });
10241
+ }
10242
+ const initialDir = path20.join(snapshotsDir, "initial");
10243
+ await restoreSnapshotDir(initialDir, process.cwd());
10244
+ for (let i = 1; i <= targetIdx; i++) {
10245
+ const cp = checkpoints[i];
10246
+ const turnDir = path20.join(snapshotsDir, cp.id);
10247
+ await restoreSnapshotDir(turnDir, process.cwd());
10248
+ if (cp.deletedFiles && cp.deletedFiles.length > 0) {
10249
+ for (const delFile of cp.deletedFiles) {
10250
+ const fullPath = path20.join(process.cwd(), delFile);
10251
+ await fs21.chmod(fullPath, 438).catch(() => {
10252
+ });
10253
+ await fs21.remove(fullPath).catch(() => {
10254
+ });
10255
+ }
10256
+ }
10257
+ }
10258
+ session.checkpoints = checkpoints.slice(0, targetIdx + 1);
10259
+ session.currentManifest = await scanWorkspace(process.cwd());
10260
+ writeEncryptedJson(LEDGER_ADVANCE_FILE, ledger);
10261
+ return true;
10262
+ } catch (err) {
10263
+ throw new Error(`Rollback failed: ${err.message}`);
10264
+ }
10265
+ },
10266
+ async cleanup(chatId) {
10267
+ try {
10268
+ const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10269
+ await fs21.remove(snapshotsDir).catch(() => {
10270
+ });
10271
+ const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10272
+ if (ledger[chatId]) {
10273
+ delete ledger[chatId];
10274
+ writeEncryptedJson(LEDGER_ADVANCE_FILE, ledger);
10275
+ }
10276
+ } catch (err) {
10277
+ }
10278
+ }
10279
+ };
10280
+ }
10281
+ });
10282
+
10283
+ // src/tools/emergency_rollback.js
10284
+ var emergency_rollback;
10285
+ var init_emergency_rollback = __esm({
10286
+ "src/tools/emergency_rollback.js"() {
10287
+ init_arg_parser();
10288
+ init_advanceRevert();
10289
+ emergency_rollback = async (args, context = {}) => {
10290
+ const parsed = parseArgs(args);
10291
+ const method = parsed.method;
10292
+ const id = parsed.id;
10293
+ const chatId = context.chatId;
10294
+ const systemSettings = context.systemSettings;
10295
+ if (!systemSettings?.advanceRollback) {
10296
+ return "ERROR: Advance Rollback feature is currently disabled in settings under Security. Tell user to enable it.";
10297
+ }
10298
+ if (!chatId) {
10299
+ return "ERROR: No active chat transaction found for rollback.";
10300
+ }
10301
+ if (method === "getCheckpoint") {
10302
+ const checkpoints = await AdvanceRevertManager.getCheckpoints(chatId);
10303
+ if (checkpoints.length === 0) {
10304
+ return "No checkpoints available.";
10305
+ }
10306
+ let output = "Available checkpoints for rollback:\n\n";
10307
+ for (const cp of checkpoints) {
10308
+ if (cp.id === "initial") {
10309
+ output += `--- Initial State (id: initial) ---
10310
+ Tools Used: None
10311
+
10312
+ `;
10313
+ } else {
10314
+ const turnNum = cp.id.replace("turn_", "");
10315
+ const toolsStr = cp.toolsUsed && cp.toolsUsed.length > 0 ? cp.toolsUsed.join(", ") : "None";
10316
+ output += `--- Turn ${turnNum} (id: ${cp.id}) ---
10317
+ Tools Used: ${toolsStr}
10318
+
10319
+ `;
10320
+ }
10321
+ }
10322
+ return output.trim();
10323
+ } else if (method === "forceRevert") {
10324
+ if (!id) {
10325
+ return "ERROR: Missing required parameter 'id' for forceRevert.";
10326
+ }
10327
+ try {
10328
+ await AdvanceRevertManager.rollbackToCheckpoint(chatId, id);
10329
+ return `SUCCESS: Repository rolled back to checkpoint [${id}].`;
10330
+ } catch (err) {
10331
+ return `ERROR: ${err.message}`;
10332
+ }
10333
+ } else {
10334
+ return `ERROR: Invalid method "${method}". Use "getCheckpoint" or "forceRevert".`;
10335
+ }
10336
+ };
10337
+ }
10338
+ });
10339
+
10047
10340
  // src/utils/tools.js
10048
10341
  var TOOL_MAP, dispatchTool;
10049
10342
  var init_tools = __esm({
@@ -10071,6 +10364,7 @@ var init_tools = __esm({
10071
10364
  init_getProgress();
10072
10365
  init_cancel();
10073
10366
  init_await();
10367
+ init_emergency_rollback();
10074
10368
  TOOL_MAP = {
10075
10369
  web_search,
10076
10370
  web_scrape,
@@ -10126,7 +10420,9 @@ var init_tools = __esm({
10126
10420
  GetProgress: getProgress,
10127
10421
  Cancel: cancel,
10128
10422
  await: awaitTool,
10129
- Await: awaitTool
10423
+ Await: awaitTool,
10424
+ EmergencyRollback: emergency_rollback,
10425
+ emergency_rollback
10130
10426
  };
10131
10427
  dispatchTool = async (toolName, args, context = {}) => {
10132
10428
  const mode = context.mode ? context.mode.toLowerCase() : "flux";
@@ -10276,8 +10572,8 @@ __export(ai_exports, {
10276
10572
  signalTermination: () => signalTermination
10277
10573
  });
10278
10574
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
10279
- import path20 from "path";
10280
- import fs21 from "fs";
10575
+ import path21, { normalize } from "path";
10576
+ import fs22 from "fs";
10281
10577
  var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, getOpenRouterStream, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10282
10578
  var init_ai = __esm({
10283
10579
  async "src/utils/ai.js"() {
@@ -10294,12 +10590,13 @@ var init_ai = __esm({
10294
10590
  init_subagent_state();
10295
10591
  init_paths();
10296
10592
  init_revert();
10593
+ init_advanceRevert();
10297
10594
  init_editor();
10298
10595
  client = null;
10299
10596
  globalSettings = {};
10300
10597
  colorMainWords = (label) => {
10301
10598
  if (!label) return label;
10302
- return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
10599
+ return label.replace(/(?:(\x1b\[\d+m))?([✔✘✖🔍📖→➕↻•🛇])(?:(\x1b\[\d+m))?\s*\b(Created|Read|Edited|Viewed|Auto-Read|List|Generated|Written|Searched|Get Map|Write Canceled|Edit Canceled|Write Cancelled|Edit Denied|Visited|Updated|Reviewed|Delegated|Background|Checked|Indexed|Analyzed|Browsed|Elevating SubAgent|Checking SubAgent Work|Started Generalist|Called Generalist|Unsupported Modality|Awaiting|Cancelled|Aligning Moon Phase|Contemplating Existence|Staring At Void|Rollback|Delaying Professionally|Negotiating With Electrons|Touching Grass (virtually)|Panicking Softly|Rethinking Career Choices|Loading Cat Videos|Giving Up Entirely|Summoning Braincell #2|Pretending To Be Busy|Waiting For Motivation DLC|Rotating Internal Screaming|Downloading More RAM|Feeding The Hamsters|Gaslighting Scheduler|Performing Dramatic Pause|Buffering Social Energy|Calculating Regret|Reading Terms And Conditions|Becoming Sentient Briefly|Contacting Ancestors)\b/ig, (match, ansiBefore, icon, ansiAfter, word) => {
10303
10600
  return `${ansiBefore || ""}${icon}${ansiAfter || ""} \x1B[95m${word}\x1B[0m`;
10304
10601
  });
10305
10602
  };
@@ -10902,7 +11199,7 @@ var init_ai = __esm({
10902
11199
  return pArgs.id || pArgs.taskId;
10903
11200
  }
10904
11201
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
10905
- return filePath ? path20.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
11202
+ return filePath ? path21.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
10906
11203
  } catch (e) {
10907
11204
  return null;
10908
11205
  }
@@ -11143,9 +11440,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11143
11440
  }
11144
11441
  })() : String(err);
11145
11442
  await new Promise((resolve) => setTimeout(resolve, 1e3));
11146
- const janitorErrDir = path20.join(LOGS_DIR, "janitor");
11147
- if (!fs21.existsSync(janitorErrDir)) fs21.mkdirSync(janitorErrDir, { recursive: true });
11148
- fs21.appendFileSync(path20.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
11443
+ const janitorErrDir = path21.join(LOGS_DIR, "janitor");
11444
+ if (!fs22.existsSync(janitorErrDir)) fs22.mkdirSync(janitorErrDir, { recursive: true });
11445
+ fs22.appendFileSync(path21.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
11149
11446
 
11150
11447
  `);
11151
11448
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -11154,8 +11451,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11154
11451
  }
11155
11452
  }
11156
11453
  if (attempts) {
11157
- const janitorErrDir = path20.join(LOGS_DIR, "janitor");
11158
- fs21.appendFileSync(path20.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
11454
+ const janitorErrDir = path21.join(LOGS_DIR, "janitor");
11455
+ fs22.appendFileSync(path21.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
11159
11456
 
11160
11457
  `);
11161
11458
  if (attempts >= MAX_JANITOR_RETRIES) {
@@ -11635,10 +11932,10 @@ ${newMemoryListStr}
11635
11932
  }
11636
11933
  })() : String(err);
11637
11934
  ;
11638
- const janitorLogDir = path20.join(LOGS_DIR, "janitor");
11639
- if (!fs21.existsSync(janitorLogDir)) fs21.mkdirSync(janitorLogDir, { recursive: true });
11640
- fs21.appendFileSync(
11641
- path20.join(janitorLogDir, "error.log"),
11935
+ const janitorLogDir = path21.join(LOGS_DIR, "janitor");
11936
+ if (!fs22.existsSync(janitorLogDir)) fs22.mkdirSync(janitorLogDir, { recursive: true });
11937
+ fs22.appendFileSync(
11938
+ path21.join(janitorLogDir, "error.log"),
11642
11939
  `[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${errLog}
11643
11940
  `
11644
11941
  );
@@ -11646,7 +11943,7 @@ ${newMemoryListStr}
11646
11943
  };
11647
11944
  compressHistory = async (settings, history, isAuto = false) => {
11648
11945
  const { chatId, aiProvider = "Google" } = settings;
11649
- const summariesFile = path20.join(SECRET_DIR, "chat-summaries.json");
11946
+ const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
11650
11947
  const flattenContext = (hist) => {
11651
11948
  return hist.filter(
11652
11949
  (m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !String(m.id).startsWith("welcome")
@@ -11720,8 +12017,8 @@ Provide a consolidated summary of the entire session.`;
11720
12017
  };
11721
12018
  deleteChatSummary = (chatId) => {
11722
12019
  try {
11723
- const summariesFile = path20.join(SECRET_DIR, "chat-summaries.json");
11724
- if (fs21.existsSync(summariesFile)) {
12020
+ const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
12021
+ if (fs22.existsSync(summariesFile)) {
11725
12022
  const summaries = readEncryptedJson(summariesFile, {});
11726
12023
  if (summaries[chatId]) {
11727
12024
  delete summaries[chatId];
@@ -11737,7 +12034,7 @@ Provide a consolidated summary of the entire session.`;
11737
12034
  if (!client && aiProvider === "Google") throw new Error("AI not initialized");
11738
12035
  const isMemoryEnabled = systemSettings?.memory !== false;
11739
12036
  const originalText = history[history.length - 1].text;
11740
- const summariesFile = path20.join(SECRET_DIR, "chat-summaries.json");
12037
+ const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
11741
12038
  let wasCompressedInStream = false;
11742
12039
  const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
11743
12040
  const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
@@ -11745,6 +12042,9 @@ Provide a consolidated summary of the entire session.`;
11745
12042
  let agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
11746
12043
  agentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
11747
12044
  await RevertManager.startTransaction(chatId, agentText);
12045
+ if (systemSettings?.advanceRollback) {
12046
+ await AdvanceRevertManager.takeInitialSnapshot(chatId);
12047
+ }
11748
12048
  TERMINATION_SIGNAL = false;
11749
12049
  let connectionPollInterval = null;
11750
12050
  try {
@@ -11969,11 +12269,12 @@ Provide a consolidated summary of the entire session.`;
11969
12269
  "log",
11970
12270
  ".nyc_output",
11971
12271
  ".sonar",
11972
- ".ruff_cache"
12272
+ ".ruff_cache",
12273
+ ".VSCodeCounter"
11973
12274
  ];
11974
12275
  const safeReaddirWithTypes = (dir) => {
11975
12276
  try {
11976
- return fs21.readdirSync(dir, { withFileTypes: true });
12277
+ return fs22.readdirSync(dir, { withFileTypes: true });
11977
12278
  } catch (e) {
11978
12279
  return [];
11979
12280
  }
@@ -11986,16 +12287,16 @@ Provide a consolidated summary of the entire session.`;
11986
12287
  if (COLLAPSED_DIRS_GLOBAL.includes(entry.name)) continue;
11987
12288
  if (entry.isDirectory()) {
11988
12289
  currentCount.value++;
11989
- countFolders(path20.join(dir, entry.name), currentCount, depth + 1);
12290
+ countFolders(path21.join(dir, entry.name), currentCount, depth + 1);
11990
12291
  }
11991
12292
  }
11992
12293
  return currentCount.value;
11993
12294
  };
11994
12295
  const getDirTree = (dir, maxDepth, prefix = "", depth = 1) => {
11995
12296
  const entries = safeReaddirWithTypes(dir);
11996
- const sep = path20.sep;
12297
+ const sep = path21.sep;
11997
12298
  if (entries.length > 100) {
11998
- return `${prefix}\u2514\u2500\u2500 ${path20.basename(dir)}${sep} ...100+ files...
12299
+ return `${prefix}\u2514\u2500\u2500 ${path21.basename(dir)}${sep} ...100+ files...
11999
12300
  `;
12000
12301
  }
12001
12302
  let result = "";
@@ -12013,7 +12314,7 @@ Provide a consolidated summary of the entire session.`;
12013
12314
  ];
12014
12315
  finalItems.forEach((item, index) => {
12015
12316
  const isLast = index === finalItems.length - 1;
12016
- const filePath = path20.join(dir, item.name);
12317
+ const filePath = path21.join(dir, item.name);
12017
12318
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
12018
12319
  const childPrefix = prefix + (isLast ? " " : "\u2502 ");
12019
12320
  if (item.isCollapsed) {
@@ -12099,10 +12400,10 @@ ${currentSummary}
12099
12400
  if (isBridgeConnected()) {
12100
12401
  ideBlock = "[IDE CONTEXT]\n";
12101
12402
  if (ideCtx.file_focused !== "none") {
12102
- const relFocused = path20.relative(process.cwd(), ideCtx.file_focused);
12403
+ const relFocused = path21.relative(process.cwd(), ideCtx.file_focused);
12103
12404
  const relOpened = (ideCtx.opened_editors || []).map((p) => {
12104
- const rel = path20.relative(process.cwd(), p);
12105
- return rel.startsWith("..") ? `[External] ${path20.basename(p)}` : rel;
12405
+ const rel = path21.relative(process.cwd(), p);
12406
+ return rel.startsWith("..") ? `[External] ${path21.basename(p)}` : rel;
12106
12407
  });
12107
12408
  ideBlock += `Focused File: ${relFocused}
12108
12409
  Cursor Line: ${ideCtx.cursor_line}
@@ -12144,7 +12445,7 @@ Cursor Line: ${ideCtx.cursor_line}
12144
12445
  }
12145
12446
  const getSumForLimit = (limit, activeFiles2) => {
12146
12447
  return activeFiles2.reduce((sum, f) => {
12147
- const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path20.resolve(process.cwd(), f.path) === path20.resolve(ideCtx.file_focused));
12448
+ const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path21.resolve(process.cwd(), f.path) === path21.resolve(ideCtx.file_focused));
12148
12449
  const fileLimit = isFocused ? Math.ceil(limit * 1.2) : limit;
12149
12450
  return sum + Math.min(f.edits.length, fileLimit);
12150
12451
  }, 0);
@@ -12178,7 +12479,7 @@ Cursor Line: ${ideCtx.cursor_line}
12178
12479
  }
12179
12480
  }
12180
12481
  for (const file of activeFiles) {
12181
- const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path20.resolve(process.cwd(), file.path) === path20.resolve(ideCtx.file_focused));
12482
+ const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path21.resolve(process.cwd(), file.path) === path21.resolve(ideCtx.file_focused));
12182
12483
  const fileLimit = isFocused ? Math.ceil(chosenLimit * 1.2) : chosenLimit;
12183
12484
  if (file.edits.length > fileLimit) {
12184
12485
  file.edits = file.edits.slice(-fileLimit);
@@ -12262,9 +12563,9 @@ ${ideCtx.warnings}
12262
12563
  endLine = matchRange[2] ? parseInt(matchRange[2], 10) : startLine;
12263
12564
  filePath = tagClean.slice(0, matchRange.index);
12264
12565
  }
12265
- const absPath = path20.resolve(process.cwd(), filePath);
12266
- if (fs21.existsSync(absPath)) {
12267
- const stats = fs21.statSync(absPath);
12566
+ const absPath = path21.resolve(process.cwd(), filePath);
12567
+ if (fs22.existsSync(absPath)) {
12568
+ const stats = fs22.statSync(absPath);
12268
12569
  if (stats.isFile()) {
12269
12570
  const pathLower = filePath.toLowerCase();
12270
12571
  const isPdf = pathLower.endsWith(".pdf");
@@ -12273,7 +12574,7 @@ ${ideCtx.warnings}
12273
12574
  const isMultimodalFile = isImage || isPdf || isOfficeFile;
12274
12575
  const isSupported = aiProvider === "Google" || MULTIMODAL_MODELS.includes(modelName);
12275
12576
  if (isMultimodalFile && !isSupported) {
12276
- const label = `\u2718 Unsupported Modality: ${path20.basename(filePath)}`;
12577
+ const label = `\u2718 Unsupported Modality: ${path21.basename(filePath)}`;
12277
12578
  let terminalWidth = 115;
12278
12579
  if (process.stdout.isTTY) {
12279
12580
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -12326,7 +12627,7 @@ ${boxMid}
12326
12627
  } else {
12327
12628
  let totalLines = "...";
12328
12629
  try {
12329
- const content = fs21.readFileSync(absPath, "utf8");
12630
+ const content = fs22.readFileSync(absPath, "utf8");
12330
12631
  totalLines = content.split("\n").length;
12331
12632
  } catch (e) {
12332
12633
  }
@@ -12386,6 +12687,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
12386
12687
  }
12387
12688
  });
12388
12689
  for (let loop = 0; loop <= MAX_LOOPS; loop++) {
12690
+ const currentTurnTools = [];
12389
12691
  wasToolCalledInLastLoop = false;
12390
12692
  if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > contextTruncationCount) {
12391
12693
  modifiedHistory = getTruncatedHistory(modifiedHistory, 6);
@@ -12970,7 +13272,7 @@ ${ideErr} [/ERROR]`;
12970
13272
  if (keyword) {
12971
13273
  detail = keyword.replace(/["']/g, "");
12972
13274
  } else if (filePath) {
12973
- detail = path20.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
13275
+ detail = path21.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
12974
13276
  } else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
12975
13277
  detail = title.replace(/["']/g, "").substring(0, 30);
12976
13278
  } else if (id && potentialTool === "get_progress") {
@@ -12999,7 +13301,7 @@ ${ideErr} [/ERROR]`;
12999
13301
  if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
13000
13302
  detail = val.substring(0, 30);
13001
13303
  } else {
13002
- detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path20.basename(val.replace(/\\/g, "/"));
13304
+ detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path21.basename(val.replace(/\\/g, "/"));
13003
13305
  }
13004
13306
  }
13005
13307
  }
@@ -13199,9 +13501,9 @@ ${ideErr} [/ERROR]`;
13199
13501
  let totalLines = "...";
13200
13502
  let actualEndLine = eLine;
13201
13503
  try {
13202
- const absPath = path20.resolve(process.cwd(), targetPath2);
13203
- if (fs21.existsSync(absPath)) {
13204
- const content = fs21.readFileSync(absPath, "utf8");
13504
+ const absPath = path21.resolve(process.cwd(), targetPath2);
13505
+ if (fs22.existsSync(absPath)) {
13506
+ const content = fs22.readFileSync(absPath, "utf8");
13205
13507
  const lines = content.split("\n").length;
13206
13508
  totalLines = lines;
13207
13509
  actualEndLine = Math.min(eLine, lines);
@@ -13221,8 +13523,8 @@ ${ideErr} [/ERROR]`;
13221
13523
  }
13222
13524
  } else if (normToolName === "list_files" || normToolName === "read_folder") {
13223
13525
  const action = normToolName === "list_files" ? "List" : "Browsed";
13224
- const path22 = parseArgs(toolCall.args).path;
13225
- label = `\u2714 ${action}: ${path22 === "." ? "./" : path22}`;
13526
+ const path23 = parseArgs(toolCall.args).path;
13527
+ label = `\u2714 ${action}: ${path23 === "." ? "./" : path23}`;
13226
13528
  } else if (normToolName === "write_file" || normToolName === "update_file") {
13227
13529
  const action = normToolName === "write_file" ? "Created" : "Edited";
13228
13530
  label = `\u2714 ${action}: ${parseArgs(toolCall.args).path || "..."}`;
@@ -13251,7 +13553,9 @@ ${ideErr} [/ERROR]`;
13251
13553
  } else if (normToolName === "cancel") {
13252
13554
  const detail2 = getToolDetail(normToolName, toolCall.args);
13253
13555
  label = `\u{1F6C7} Cancelled${detail2 ? `: ${detail2}` : ""}`;
13254
- } else if (normToolName === "await") {
13556
+ } else if (normToolName === "EmergencyRollback") {
13557
+ label = `\u2714 Rollback`;
13558
+ } else if (normToolName === "await" || normToolName === "Await") {
13255
13559
  const { time } = parseArgs(toolCall.args);
13256
13560
  let sec = parseFloat(time) || 0;
13257
13561
  if (sec < 10) sec = 10;
@@ -13305,7 +13609,7 @@ ${ideErr} [/ERROR]`;
13305
13609
  const { command } = parseArgs(toolCall.args);
13306
13610
  if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
13307
13611
  const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
13308
- const currentDrive = path20.resolve(process.cwd()).substring(0, 3).toLowerCase();
13612
+ const currentDrive = path21.resolve(process.cwd()).substring(0, 3).toLowerCase();
13309
13613
  const splitCommands = (cmdString) => {
13310
13614
  const commands = [];
13311
13615
  let current = "";
@@ -13434,8 +13738,8 @@ ${ideErr} [/ERROR]`;
13434
13738
  const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
13435
13739
  if (targetPath) {
13436
13740
  const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
13437
- const absoluteTarget = path20.resolve(targetPath);
13438
- const absoluteCwd = path20.resolve(process.cwd());
13741
+ const absoluteTarget = path21.resolve(targetPath);
13742
+ const absoluteCwd = path21.resolve(process.cwd());
13439
13743
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
13440
13744
  const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace.`;
13441
13745
  if (normToolName === "write_file" || normToolName === "update_file") {
@@ -13624,18 +13928,18 @@ ${boxMid}`) };
13624
13928
  const toolArgs = parseArgs(toolCall.args);
13625
13929
  const { path: filePath } = toolArgs;
13626
13930
  if (filePath) {
13627
- const absPath = path20.resolve(process.cwd(), filePath);
13628
- const normalize = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
13629
- const normAbsPath = normalize(absPath);
13931
+ const absPath = path21.resolve(process.cwd(), filePath);
13932
+ const normalize2 = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
13933
+ const normAbsPath = normalize2(absPath);
13630
13934
  let originalContent = "";
13631
13935
  let hasOriginal = false;
13632
13936
  const currentIDE = await getIDEContext();
13633
- const normFocused = normalize(currentIDE?.file_focused);
13937
+ const normFocused = normalize2(currentIDE?.file_focused);
13634
13938
  if (currentIDE && normFocused === normAbsPath && currentIDE.full_content) {
13635
13939
  originalContent = currentIDE.full_content;
13636
13940
  hasOriginal = true;
13637
- } else if (fs21.existsSync(absPath)) {
13638
- originalContent = fs21.readFileSync(absPath, "utf8");
13941
+ } else if (fs22.existsSync(absPath)) {
13942
+ originalContent = fs22.readFileSync(absPath, "utf8");
13639
13943
  hasOriginal = true;
13640
13944
  }
13641
13945
  originalContentForReporting = originalContent;
@@ -13662,9 +13966,9 @@ ${boxMid}`) };
13662
13966
  const successes = patchResults.filter((r) => r.success);
13663
13967
  const failures = patchResults.filter((r) => !r.success);
13664
13968
  if (successes.length === 0) {
13665
- const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path20.basename(absPath)}].
13969
+ const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path21.basename(absPath)}].
13666
13970
  ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
13667
- const errorLabel = `\u2714 Edited: ${path20.basename(absPath)}`.toUpperCase();
13971
+ const errorLabel = `\u2714 Edited: ${path21.basename(absPath)}`.toUpperCase();
13668
13972
  let terminalWidth = 115;
13669
13973
  if (process.stdout.isTTY) {
13670
13974
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -13682,19 +13986,19 @@ ${boxMid}}`) };
13682
13986
  continue;
13683
13987
  }
13684
13988
  }
13685
- yield { type: "status", content: `Opening Diff in IDE: ${path20.basename(absPath)}...` };
13989
+ yield { type: "status", content: `Opening Diff in IDE: ${path21.basename(absPath)}...` };
13686
13990
  showDiffInIDE(absPath, originalContent, modifiedContent);
13687
13991
  diffOpened = true;
13688
13992
  await new Promise((r) => setTimeout(r, 50));
13689
13993
  } else if (normToolName === "write_file") {
13690
13994
  const rawContent = toolArgs.content || toolArgs.newContent || "";
13691
13995
  const modifiedContent = rawContent.endsWith("\n") ? rawContent : rawContent + "\n";
13692
- if (!fs21.existsSync(absPath)) {
13996
+ if (!fs22.existsSync(absPath)) {
13693
13997
  isNewFileCreated = true;
13694
- fs21.mkdirSync(path20.dirname(absPath), { recursive: true });
13695
- fs21.writeFileSync(absPath, "", "utf8");
13998
+ fs22.mkdirSync(path21.dirname(absPath), { recursive: true });
13999
+ fs22.writeFileSync(absPath, "", "utf8");
13696
14000
  }
13697
- yield { type: "status", content: `Opening New File Diff in IDE: ${path20.basename(absPath)}...` };
14001
+ yield { type: "status", content: `Opening New File Diff in IDE: ${path21.basename(absPath)}...` };
13698
14002
  showDiffInIDE(absPath, "", modifiedContent);
13699
14003
  diffOpened = true;
13700
14004
  await new Promise((r) => setTimeout(r, 50));
@@ -13730,11 +14034,11 @@ ${boxMid}}`) };
13730
14034
  if (normToolName === "write_file" || normToolName === "update_file") {
13731
14035
  const { path: filePath } = parseArgs(toolCall.args);
13732
14036
  if (filePath) {
13733
- const absPath = path20.resolve(process.cwd(), filePath);
14037
+ const absPath = path21.resolve(process.cwd(), filePath);
13734
14038
  closeDiffInIDE(absPath, approval);
13735
- if (approval === "deny" && isNewFileCreated && fs21.existsSync(absPath)) {
14039
+ if (approval === "deny" && isNewFileCreated && fs22.existsSync(absPath)) {
13736
14040
  try {
13737
- fs21.unlinkSync(absPath);
14041
+ fs22.unlinkSync(absPath);
13738
14042
  } catch (e) {
13739
14043
  }
13740
14044
  }
@@ -13746,13 +14050,13 @@ ${boxMid}}`) };
13746
14050
  }
13747
14051
  if (approval === "allow" && diffOpened && isBridgeConnected()) {
13748
14052
  const { path: filePath } = parseArgs(toolCall.args);
13749
- const absPath = path20.resolve(process.cwd(), filePath);
14053
+ const absPath = path21.resolve(process.cwd(), filePath);
13750
14054
  const finalIDE = await getIDEContext();
13751
14055
  let finalContent = "";
13752
14056
  if (finalIDE && finalIDE.file_focused === absPath && finalIDE.full_content) {
13753
14057
  finalContent = finalIDE.full_content;
13754
- } else if (fs21.existsSync(absPath)) {
13755
- finalContent = fs21.readFileSync(absPath, "utf8");
14058
+ } else if (fs22.existsSync(absPath)) {
14059
+ finalContent = fs22.readFileSync(absPath, "utf8");
13756
14060
  }
13757
14061
  const verifiedLines = finalContent.split(/\r?\n/);
13758
14062
  const verifiedLineCount = verifiedLines.length;
@@ -13915,7 +14219,7 @@ ${boxBottom}`}`) };
13915
14219
  try {
13916
14220
  const { path: filePath } = parseArgs(toolCall.args);
13917
14221
  if (filePath) {
13918
- const absPath = path20.resolve(process.cwd(), filePath);
14222
+ const absPath = path21.resolve(process.cwd(), filePath);
13919
14223
  const currentIDE = await getIDEContext();
13920
14224
  if (currentIDE && currentIDE.file_focused === absPath && currentIDE.full_content) {
13921
14225
  execToolContext.forcedContent = currentIDE.full_content;
@@ -13924,12 +14228,13 @@ ${boxBottom}`}`) };
13924
14228
  } catch (e) {
13925
14229
  }
13926
14230
  }
14231
+ currentTurnTools.push(normToolName);
13927
14232
  let result = await dispatchTool(normToolName, toolCall.args, execToolContext);
13928
14233
  yield { type: "spinner", content: true };
13929
14234
  if ((normToolName === "write_file" || normToolName === "update_file") && result.startsWith("SUCCESS")) {
13930
14235
  const { path: filePath } = parseArgs(toolCall.args);
13931
14236
  if (filePath) {
13932
- const absPath = path20.resolve(process.cwd(), filePath);
14237
+ const absPath = path21.resolve(process.cwd(), filePath);
13933
14238
  openFileInEditor(absPath);
13934
14239
  }
13935
14240
  }
@@ -14173,9 +14478,9 @@ ${colorMainWords(output)}` };
14173
14478
  })() : String(err);
14174
14479
  ;
14175
14480
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
14176
- const agentErrDir = path20.join(LOGS_DIR, "agent");
14177
- if (!fs21.existsSync(agentErrDir)) fs21.mkdirSync(agentErrDir, { recursive: true });
14178
- fs21.appendFileSync(path20.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
14481
+ const agentErrDir = path21.join(LOGS_DIR, "agent");
14482
+ if (!fs22.existsSync(agentErrDir)) fs22.mkdirSync(agentErrDir, { recursive: true });
14483
+ fs22.appendFileSync(path21.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
14179
14484
 
14180
14485
  ----------------------------------------------------------------------
14181
14486
 
@@ -14222,7 +14527,7 @@ ${recoveryText}`
14222
14527
  yield { type: "status", content: `Error Occured. Recovering Stream...` };
14223
14528
  } else {
14224
14529
  throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
14225
- Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14530
+ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14226
14531
  }
14227
14532
  } else {
14228
14533
  if (retryCount <= MAX_RETRIES) {
@@ -14240,7 +14545,7 @@ Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14240
14545
  yield { type: "status", content: `Trying to reach ${modelName}...` };
14241
14546
  } else {
14242
14547
  throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
14243
- Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14548
+ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14244
14549
  }
14245
14550
  }
14246
14551
  }
@@ -14313,6 +14618,9 @@ Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14313
14618
  isStutteringLoop = false;
14314
14619
  isGeneralLoop = false;
14315
14620
  }
14621
+ if (systemSettings?.advanceRollback) {
14622
+ await AdvanceRevertManager.recordTurnDelta(chatId, loop + 1, currentTurnTools);
14623
+ }
14316
14624
  wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
14317
14625
  }
14318
14626
  modifiedHistory.forEach((msg) => {
@@ -14343,10 +14651,10 @@ Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14343
14651
  }
14344
14652
  })() : String(err);
14345
14653
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
14346
- const agentErrDir = path20.join(LOGS_DIR, "agent");
14654
+ const agentErrDir = path21.join(LOGS_DIR, "agent");
14347
14655
  yield { type: "text", content: `\u274C CRITICAL ERROR: ${errLog}` };
14348
- if (!fs21.existsSync(agentErrDir)) fs21.mkdirSync(agentErrDir, { recursive: true });
14349
- fs21.appendFileSync(path20.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${errLog}
14656
+ if (!fs22.existsSync(agentErrDir)) fs22.mkdirSync(agentErrDir, { recursive: true });
14657
+ fs22.appendFileSync(path21.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${errLog}
14350
14658
 
14351
14659
  ----------------------------------------------------------------------
14352
14660
 
@@ -14361,6 +14669,9 @@ Error Log can be found in ${path20.join(LOGS_DIR, "agent", "error.log")}`);
14361
14669
  connectionPollInterval = null;
14362
14670
  }
14363
14671
  await RevertManager.commitTransaction();
14672
+ if (systemSettings?.advanceRollback) {
14673
+ await AdvanceRevertManager.cleanup(chatId);
14674
+ }
14364
14675
  }
14365
14676
  yield { type: "status", content: null };
14366
14677
  };
@@ -14387,6 +14698,7 @@ TOOL POLICY:
14387
14698
  - FileMap >>> ReadFile to understand file efficiently
14388
14699
  - Want spefific STRING across project/file? SearchKeyword >> Guessing/ReadFile
14389
14700
  - HUGE FILES? SearchKeyword >> FileMap/Full Read
14701
+ - NO Terminal Access
14390
14702
  -- PROVIDED TOOLS --
14391
14703
  ${Object.values(SUBAGENT_TOOL_DEFINITIONS).join("\n")}
14392
14704
 
@@ -14468,11 +14780,11 @@ ${cleanResponse}
14468
14780
  } else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
14469
14781
  label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m`;
14470
14782
  } else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
14471
- const path22 = parseArgs(toolCall.args).path || "...";
14472
- label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path22}`;
14783
+ const path23 = parseArgs(toolCall.args).path || "...";
14784
+ label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path23}`;
14473
14785
  } else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
14474
- const path22 = parseArgs(toolCall.args).path || "...";
14475
- label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path22}`;
14786
+ const path23 = parseArgs(toolCall.args).path || "...";
14787
+ label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path23}`;
14476
14788
  } else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
14477
14789
  label = `\u2714 \x1B[95mIndexed\x1B[0m`;
14478
14790
  } else if (normalizedToolName === "await") {
@@ -15338,7 +15650,7 @@ var init_RevertModal = __esm({
15338
15650
  import puppeteer4 from "puppeteer";
15339
15651
  import { exec } from "child_process";
15340
15652
  import { promisify } from "util";
15341
- import fs22 from "fs";
15653
+ import fs23 from "fs";
15342
15654
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
15343
15655
  var init_setup = __esm({
15344
15656
  "src/utils/setup.js"() {
@@ -15347,11 +15659,11 @@ var init_setup = __esm({
15347
15659
  checkPuppeteerReady = () => {
15348
15660
  try {
15349
15661
  const pptrConfig = getPuppeteerConfig();
15350
- if (pptrConfig.executablePath && fs22.existsSync(pptrConfig.executablePath)) {
15662
+ if (pptrConfig.executablePath && fs23.existsSync(pptrConfig.executablePath)) {
15351
15663
  return true;
15352
15664
  }
15353
15665
  const exePath = puppeteer4.executablePath();
15354
- const exists = exePath && fs22.existsSync(exePath);
15666
+ const exists = exePath && fs23.existsSync(exePath);
15355
15667
  if (exists) return true;
15356
15668
  } catch (e) {
15357
15669
  return false;
@@ -15384,8 +15696,8 @@ __export(app_exports, {
15384
15696
  import os5 from "os";
15385
15697
  import React15, { useState as useState14, useEffect as useEffect11, useRef as useRef4, useMemo as useMemo2 } from "react";
15386
15698
  import { Box as Box14, Text as Text15, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
15387
- import fs23 from "fs-extra";
15388
- import path21 from "path";
15699
+ import fs24 from "fs-extra";
15700
+ import path22 from "path";
15389
15701
  import { exec as exec2 } from "child_process";
15390
15702
  import { fileURLToPath as fileURLToPath2 } from "url";
15391
15703
  import TextInput4 from "ink-text-input";
@@ -15630,10 +15942,10 @@ function App({ args = [] }) {
15630
15942
  const kbPath = getKeybindingsPath(ideName);
15631
15943
  if (!kbPath) return;
15632
15944
  try {
15633
- await fs23.ensureDir(path21.dirname(kbPath));
15945
+ await fs24.ensureDir(path22.dirname(kbPath));
15634
15946
  let bindings = [];
15635
- if (fs23.existsSync(kbPath)) {
15636
- const content = fs23.readFileSync(kbPath, "utf8").trim();
15947
+ if (fs24.existsSync(kbPath)) {
15948
+ const content = fs24.readFileSync(kbPath, "utf8").trim();
15637
15949
  if (content) {
15638
15950
  try {
15639
15951
  bindings = parseJsonc(content);
@@ -15653,7 +15965,7 @@ function App({ args = [] }) {
15653
15965
  },
15654
15966
  "when": "terminalFocus"
15655
15967
  });
15656
- fs23.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
15968
+ fs24.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
15657
15969
  cachedShortcut = "Shift + Enter";
15658
15970
  setMessages((prev) => {
15659
15971
  setCompletedIndex(prev.length + 1);
@@ -16329,7 +16641,7 @@ function App({ args = [] }) {
16329
16641
  useEffect11(() => {
16330
16642
  async function init() {
16331
16643
  try {
16332
- const pkg = JSON.parse(fs23.readFileSync(path21.join(process.cwd(), "package.json"), "utf8"));
16644
+ const pkg = JSON.parse(fs24.readFileSync(path22.join(process.cwd(), "package.json"), "utf8"));
16333
16645
  initBridge(versionFluxflow || pkg.version || "2.0.0");
16334
16646
  } catch (e) {
16335
16647
  initBridge("2.0.0");
@@ -16452,7 +16764,7 @@ function App({ args = [] }) {
16452
16764
  if (!parsedArgs.playground) {
16453
16765
  deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
16454
16766
  });
16455
- fs23.remove(path21.join(DATA_DIR, "playground")).catch(() => {
16767
+ fs24.remove(path22.join(DATA_DIR, "playground")).catch(() => {
16456
16768
  });
16457
16769
  }
16458
16770
  performVersionCheck(false, freshSettings);
@@ -16486,9 +16798,9 @@ function App({ args = [] }) {
16486
16798
  }
16487
16799
  }
16488
16800
  if (parsedArgs.playground) {
16489
- const playgroundDir = path21.join(DATA_DIR, "playground");
16801
+ const playgroundDir = path22.join(DATA_DIR, "playground");
16490
16802
  try {
16491
- fs23.ensureDirSync(playgroundDir);
16803
+ fs24.ensureDirSync(playgroundDir);
16492
16804
  process.chdir(playgroundDir);
16493
16805
  } catch (e) {
16494
16806
  }
@@ -16529,8 +16841,8 @@ function App({ args = [] }) {
16529
16841
  if (kbPath) {
16530
16842
  try {
16531
16843
  let bindings = [];
16532
- if (fs23.existsSync(kbPath)) {
16533
- const content = fs23.readFileSync(kbPath, "utf8").trim();
16844
+ if (fs24.existsSync(kbPath)) {
16845
+ const content = fs24.readFileSync(kbPath, "utf8").trim();
16534
16846
  if (content) {
16535
16847
  bindings = parseJsonc(content);
16536
16848
  }
@@ -17063,22 +17375,22 @@ ${cleanText}`, color: "magenta" }];
17063
17375
  });
17064
17376
  break;
17065
17377
  }
17066
- const src = path21.join(DATA_DIR, "playground");
17067
- const dest = path21.join(parsedArgs.originalCwd, "playground-export");
17378
+ const src = path22.join(DATA_DIR, "playground");
17379
+ const dest = path22.join(parsedArgs.originalCwd, "playground-export");
17068
17380
  const moveFiles = async () => {
17069
17381
  try {
17070
17382
  setMessages((prev) => {
17071
17383
  setCompletedIndex(prev.length + 1);
17072
17384
  return [...prev, { id: Date.now(), role: "system", text: `[PLAYGROUND] Exporting playground content to ${dest}`, isMeta: true }];
17073
17385
  });
17074
- await fs23.ensureDir(dest);
17386
+ await fs24.ensureDir(dest);
17075
17387
  const excludeDirs = ["node_modules", ".git", ".venv", "venv", "env", ".next", "dist", "build", ".cache"];
17076
- await fs23.copy(src, dest, {
17388
+ await fs24.copy(src, dest, {
17077
17389
  overwrite: true,
17078
17390
  filter: (srcPath) => {
17079
- const relative = path21.relative(src, srcPath);
17391
+ const relative = path22.relative(src, srcPath);
17080
17392
  if (!relative) return true;
17081
- const parts2 = relative.split(path21.sep);
17393
+ const parts2 = relative.split(path22.sep);
17082
17394
  return !parts2.some((part) => excludeDirs.includes(part));
17083
17395
  }
17084
17396
  });
@@ -17138,7 +17450,7 @@ ${cleanText}`, color: "magenta" }];
17138
17450
  }
17139
17451
  }
17140
17452
  setTimeout(() => {
17141
- fs23.emptyDir(path21.join(DATA_DIR, "playground")).catch((err) => {
17453
+ fs24.emptyDir(path22.join(DATA_DIR, "playground")).catch((err) => {
17142
17454
  setMessages((prev) => {
17143
17455
  const newMsgs = [...prev, {
17144
17456
  id: "playground-" + Date.now(),
@@ -17435,7 +17747,7 @@ ${cleanText}`, color: "magenta" }];
17435
17747
  }
17436
17748
  case "/export": {
17437
17749
  const exportFile = `export-fluxflow-${chatId}.txt`;
17438
- const exportPath = path21.join(process.cwd(), exportFile);
17750
+ const exportPath = path22.join(process.cwd(), exportFile);
17439
17751
  const exportLines = [];
17440
17752
  let insideAgentBlock = false;
17441
17753
  for (let i = 0; i < messages.length; i++) {
@@ -17487,7 +17799,7 @@ ${cleanText}`, color: "magenta" }];
17487
17799
  }
17488
17800
  const fileContent = exportLines.join("\n");
17489
17801
  try {
17490
- fs23.writeFileSync(exportPath, fileContent, "utf8");
17802
+ fs24.writeFileSync(exportPath, fileContent, "utf8");
17491
17803
  setMessages((prev) => {
17492
17804
  setCompletedIndex(prev.length + 1);
17493
17805
  return [...prev, {
@@ -17534,12 +17846,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
17534
17846
  setCompletedIndex(prev.length + 1);
17535
17847
  return [...prev, { id: Date.now(), role: "system", text: "[NUCLEAR] Initiating reset...", isMeta: true }];
17536
17848
  });
17537
- if (fs23.existsSync(LOGS_DIR)) fs23.removeSync(LOGS_DIR);
17538
- if (fs23.existsSync(SECRET_DIR)) fs23.removeSync(SECRET_DIR);
17539
- if (fs23.existsSync(SETTINGS_FILE)) fs23.removeSync(SETTINGS_FILE);
17849
+ if (fs24.existsSync(LOGS_DIR)) fs24.removeSync(LOGS_DIR);
17850
+ if (fs24.existsSync(SECRET_DIR)) fs24.removeSync(SECRET_DIR);
17851
+ if (fs24.existsSync(SETTINGS_FILE)) fs24.removeSync(SETTINGS_FILE);
17540
17852
  try {
17541
- const items = fs23.readdirSync(FLUXFLOW_DIR);
17542
- if (items.length === 0) fs23.removeSync(FLUXFLOW_DIR);
17853
+ const items = fs24.readdirSync(FLUXFLOW_DIR);
17854
+ if (items.length === 0) fs24.removeSync(FLUXFLOW_DIR);
17543
17855
  } catch (e) {
17544
17856
  }
17545
17857
  setTimeout(() => {
@@ -17661,15 +17973,15 @@ ${list || "No saved chats found."}`, isMeta: true }];
17661
17973
  # SKILLS & WORKFLOWS
17662
17974
  - [Define custom step-by-step recipes for this project here]
17663
17975
  `;
17664
- const filePath = path21.join(process.cwd(), "FluxFlow.md");
17665
- if (fs23.pathExistsSync(filePath)) {
17976
+ const filePath = path22.join(process.cwd(), "FluxFlow.md");
17977
+ if (fs24.pathExistsSync(filePath)) {
17666
17978
  setMessages((prev) => {
17667
17979
  setCompletedIndex(prev.length + 1);
17668
17980
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
17669
17981
  });
17670
17982
  } else {
17671
17983
  try {
17672
- fs23.writeFileSync(filePath, template);
17984
+ fs24.writeFileSync(filePath, template);
17673
17985
  setMessages((prev) => {
17674
17986
  setCompletedIndex(prev.length + 1);
17675
17987
  return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "[SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
@@ -19065,6 +19377,23 @@ Selection: ${val}`,
19065
19377
  }
19066
19378
  }
19067
19379
  )));
19380
+ case "advanceRollbackDanger":
19381
+ return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, paddingTop: 0, width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true }, "\u26A0 Emergency Rollback Notice"), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1 }, "When enabled, full repo snapshots exist only during active AI turns."), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1 }, "If catastrophic changes occur during a turn, avoid abruptly stopping the agent unless absolutely necessary (external damages out of codebase)."), /* @__PURE__ */ React15.createElement(Text15, null, "The agent may be able to automatically restore the repo to a safe state."), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1 }, "Once the turn ends, emergency snapshots are deleted and standard /revert takes over which may not retain full repo content."), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
19382
+ CommandMenu,
19383
+ {
19384
+ title: "Confirm",
19385
+ items: [
19386
+ { label: "I understand and wish to enable", value: "on" },
19387
+ { label: "Keep Off", value: "off" }
19388
+ ],
19389
+ onSelect: (item) => {
19390
+ if (item.value === "on") {
19391
+ setSystemSettings((s) => ({ ...s, advanceRollback: true }));
19392
+ }
19393
+ setActiveView("settings");
19394
+ }
19395
+ }
19396
+ )));
19068
19397
  case "externalDanger":
19069
19398
  return /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, "SECURITY WARNING: EXTERNAL WORKSPACE ACCESS"), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1 }, "Turning this ON allows the agent to execute tools (Read/Write/Exec) outside of the current active workspace directory."), /* @__PURE__ */ React15.createElement(Text15, { marginTop: 1, color: "white" }, "RISKS INVOLVED:"), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 Access to sensitive system files (SSH keys, Browser data, etc.)"), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 Potential for accidental or malicious deletion of OS-critical files."), /* @__PURE__ */ React15.createElement(Text15, null, "\u2022 Unauthorized script execution across your entire file system."), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React15.createElement(
19070
19399
  CommandMenu,
@@ -19712,11 +20041,11 @@ var init_app = __esm({
19712
20041
  if (process.platform === "win32") {
19713
20042
  const appData = process.env.APPDATA;
19714
20043
  if (!appData) return null;
19715
- return path21.join(appData, dirName, "User", "keybindings.json");
20044
+ return path22.join(appData, dirName, "User", "keybindings.json");
19716
20045
  } else if (process.platform === "darwin") {
19717
- return path21.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
20046
+ return path22.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
19718
20047
  } else {
19719
- return path21.join(home, ".config", dirName, "User", "keybindings.json");
20048
+ return path22.join(home, ".config", dirName, "User", "keybindings.json");
19720
20049
  }
19721
20050
  };
19722
20051
  parseJsonc = (content) => {
@@ -19762,8 +20091,8 @@ var init_app = __esm({
19762
20091
  DOCS_URL = "https://fluxflow-cli.onrender.com/";
19763
20092
  linesAdded = 0;
19764
20093
  linesRemoved = 0;
19765
- packageJsonPath = path21.join(path21.dirname(fileURLToPath2(import.meta.url)), "../package.json");
19766
- packageJson = JSON.parse(fs23.readFileSync(packageJsonPath, "utf8"));
20094
+ packageJsonPath = path22.join(path22.dirname(fileURLToPath2(import.meta.url)), "../package.json");
20095
+ packageJson = JSON.parse(fs24.readFileSync(packageJsonPath, "utf8"));
19767
20096
  versionFluxflow = packageJson.version;
19768
20097
  updatedOn = packageJson.date || "2026-05-20";
19769
20098
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React15.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", padding: 0, width: "100%" }, /* @__PURE__ */ React15.createElement(Box14, { paddingX: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "white", bold: true, underline: true }, data.startsWith("/btw") ? "QUESTION" : "STEERING HINT", " RESOLUTION")), /* @__PURE__ */ React15.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, null, "The agent already finished the task before your ", data.startsWith("/btw") ? "question" : "hint", " was consumed.")), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React15.createElement(Text15, { italic: true, color: "gray" }, '"', data.replace("/btw", "").trim(), '"')), /* @__PURE__ */ React15.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React15.createElement(Text15, { color: "grey" }, "How would you like to proceed?")), /* @__PURE__ */ React15.createElement(Box14, { marginTop: 0 }, /* @__PURE__ */ React15.createElement(
@@ -19859,19 +20188,19 @@ var init_app = __esm({
19859
20188
  const fileList = [];
19860
20189
  const scan = (currentDir) => {
19861
20190
  try {
19862
- const files = fs23.readdirSync(currentDir);
20191
+ const files = fs24.readdirSync(currentDir);
19863
20192
  for (const file of files) {
19864
20193
  if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
19865
20194
  continue;
19866
20195
  }
19867
- const filePath = path21.join(currentDir, file);
19868
- const stat = fs23.statSync(filePath);
20196
+ const filePath = path22.join(currentDir, file);
20197
+ const stat = fs24.statSync(filePath);
19869
20198
  if (stat.isDirectory()) {
19870
20199
  scan(filePath);
19871
20200
  } else {
19872
20201
  fileList.push({
19873
20202
  name: file,
19874
- relativePath: path21.relative(process.cwd(), filePath)
20203
+ relativePath: path22.relative(process.cwd(), filePath)
19875
20204
  });
19876
20205
  }
19877
20206
  }
@@ -19994,11 +20323,11 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
19994
20323
  const isVersion = args.includes("--version") || args.includes("-v");
19995
20324
  const isUpdate = args[0] === "--update";
19996
20325
  if (isVersion || isHelp || isHelpCommands || isUpdate) {
19997
- const fs24 = await import("fs");
19998
- const path22 = await import("path");
20326
+ const fs25 = await import("fs");
20327
+ const path23 = await import("path");
19999
20328
  const { fileURLToPath: fileURLToPath4 } = await import("url");
20000
- const packageJsonPath2 = path22.join(path22.dirname(fileURLToPath4(import.meta.url)), "../package.json");
20001
- const packageJson2 = JSON.parse(fs24.readFileSync(packageJsonPath2, "utf8"));
20329
+ const packageJsonPath2 = path23.join(path23.dirname(fileURLToPath4(import.meta.url)), "../package.json");
20330
+ const packageJson2 = JSON.parse(fs25.readFileSync(packageJsonPath2, "utf8"));
20002
20331
  const versionFluxflow2 = packageJson2.version;
20003
20332
  if (isVersion) {
20004
20333
  console.log(`v${versionFluxflow2}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fluxflow-cli",
3
- "version": "3.0.22",
3
+ "version": "3.1.0",
4
4
  "date": "2026-07-05",
5
5
  "description": "A High-Fidelity Agentic CLI with Sub-Agents for the Flux Era.",
6
6
  "keywords": [