fluxflow-cli 1.13.6 → 1.14.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 (3) hide show
  1. package/README.md +6 -0
  2. package/dist/fluxflow.js +1277 -915
  3. package/package.json +1 -1
package/dist/fluxflow.js CHANGED
@@ -463,6 +463,7 @@ var init_ChatLayout = __esm({
463
463
  { cmd: "/help", desc: "Show all available commands" },
464
464
  { cmd: "/clear", desc: "Clear terminal screen" },
465
465
  { cmd: "/resume", desc: "Load previous session" },
466
+ { cmd: "/revert", desc: "Revert codebase to checkpoint" },
466
467
  { cmd: "/save", desc: "Force save current chat" },
467
468
  { cmd: "/export", desc: "Export current chat in a .txt file" },
468
469
  { cmd: "/chats", desc: "List all chat sessions" },
@@ -814,9 +815,11 @@ var init_crypto = __esm({
814
815
  // src/utils/paths.js
815
816
  var paths_exports = {};
816
817
  __export(paths_exports, {
818
+ BACKUPS_DIR: () => BACKUPS_DIR,
817
819
  DATA_DIR: () => DATA_DIR,
818
820
  FLUXFLOW_DIR: () => FLUXFLOW_DIR,
819
821
  HISTORY_FILE: () => HISTORY_FILE,
822
+ LEDGER_FILE: () => LEDGER_FILE,
820
823
  LOGS_DIR: () => LOGS_DIR,
821
824
  MEMORIES_FILE: () => MEMORIES_FILE,
822
825
  SECRET_DIR: () => SECRET_DIR,
@@ -829,7 +832,7 @@ import os2 from "os";
829
832
  import path2 from "path";
830
833
  import fs2 from "fs";
831
834
  import crypto2 from "crypto";
832
- var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE;
835
+ var FLUXFLOW_DIR, SETTINGS_FILE, externalDir, DATA_DIR, LOGS_DIR, SECRET_DIR, HISTORY_FILE, USAGE_FILE, MEMORIES_FILE, TEMP_MEM_FILE, TEMP_MEM_CHAT_FILE, BACKUPS_DIR, LEDGER_FILE;
833
836
  var init_paths = __esm({
834
837
  "src/utils/paths.js"() {
835
838
  FLUXFLOW_DIR = path2.join(os2.homedir(), ".fluxflow");
@@ -870,6 +873,8 @@ var init_paths = __esm({
870
873
  MEMORIES_FILE = path2.join(SECRET_DIR, "memories.json");
871
874
  TEMP_MEM_FILE = path2.join(SECRET_DIR, "memory-temp.json");
872
875
  TEMP_MEM_CHAT_FILE = path2.join(SECRET_DIR, "temp-memory-chat.json");
876
+ BACKUPS_DIR = path2.join(DATA_DIR, "backups");
877
+ LEDGER_FILE = path2.join(SECRET_DIR, "ledger.json");
873
878
  }
874
879
  });
875
880
 
@@ -962,21 +967,21 @@ Suggest best options; don't ask for preferences. System handles the rest
962
967
  ${mode === "Flux" ? `- FILE TOOLS (path = relative to CWD) -
963
968
  1. [tool:functions.ReadFile(path="...", start_line=N, end_line=N)]. Reads contents. Supports images/docs. User gives image/doc: VIEW FIRST
964
969
  2. [tool:functions.ReadFolder(path="...")]. Detailed DIR stats
965
- 3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? -> update_file > write_file
966
- 4. [tool:functions.PatchFile(path="...", content_to_replace="exact old content", content_to_add="new content")]. Surgical patching. Unsure content_to_replace? -> view_file >> guessing.
967
- 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. **USE PROPER PROACTIVE A4 PAGE BREAKS**. HTML/CSS for PREMIUM layout (100vh/vw). No manual footers
970
+ 3. [tool:functions.WriteFile(path="...", content="...")]. Creates/Overwrites. File Exist? PatchFile > WriteFile
971
+ 4. [tool:functions.PatchFile(path="...", replaceContent="exact old content", newContent="new content")]. Surgical patching. Unsure replaceContent? ReadFile > guessing
972
+ 5. [tool:functions.WritePDF(path="...", content="...", orientation="...")]. PROACTIVE A4 PAGE BREAKS MUST IN CSS. HTML/CSS for PREMIUM layout (100vh/vw). No manual footers
968
973
  6. [tool:functions.WriteDoc(path="...", content="...")]. A4 Word doc. Proper margins and page breaks
969
- 7. [tool:functions.Run(command="...")]. Runs a ${osDetected === "Windows" ? "Windows CMD" : "Bash"} command. Destructive/Irreversible ops -> ask user
974
+ 7. [tool:functions.Run(command="...")]. Runs a ${osDetected === "Windows" ? "Windows CMD" : "Bash"} command. Destructive/Irreversible ops -> Ask user
970
975
  8. [tool:functions.SearchKeyword(keyword="...")]. Global search. Finds definitions/logic without reading every file
971
976
  9. [tool:functions.GenerateImage(path="... png", prompt="detailed", ratio="16:9, 9:16, 1:1, 4:3, 3:4")]. AI images. Usage: Mockups, PDF thumbnails, any visual content
972
977
 
973
978
  - VERIFY RESULT CONTENTS. Fix errors. No hallucinations
974
- - File tools > code chat
979
+ - File tools > long chat
975
980
 
976
981
  - Escape quotes: \\" for code strings
977
982
  - Literal escapes: Double-escape sequences (e.g., \\\\n, \\\\t)
978
983
  - File structure: Real newlines for code formatting`.trim() : `
979
- - DEV TOOLS ARE NOT AVAILABLE IN FLOW MODE`.trim()}
984
+ - FILE TOOLS ARE NOT AVAILABLE IN FLOW MODE`.trim()}
980
985
 
981
986
  - Results: Passed as [TOOL RESULT] (system)
982
987
  - Tool calls: End with [turn: continue]. Only use [turn: finish] after verifying goals
@@ -1165,15 +1170,168 @@ Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString([], { year:
1165
1170
  }
1166
1171
  });
1167
1172
 
1168
- // src/utils/history.js
1173
+ // src/utils/revert.js
1169
1174
  import fs5 from "fs-extra";
1170
1175
  import path4 from "path";
1176
+ var currentTransaction, RevertManager;
1177
+ var init_revert = __esm({
1178
+ "src/utils/revert.js"() {
1179
+ init_paths();
1180
+ init_crypto();
1181
+ fs5.ensureDirSync(BACKUPS_DIR);
1182
+ currentTransaction = null;
1183
+ RevertManager = {
1184
+ /**
1185
+ * Initializes a new transaction before a prompt starts processing.
1186
+ */
1187
+ async startTransaction(chatId, promptText) {
1188
+ currentTransaction = {
1189
+ id: `tx_prompt_${Date.now()}`,
1190
+ chatId,
1191
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1192
+ prompt: promptText.trim(),
1193
+ changes: [],
1194
+ reverted: false
1195
+ };
1196
+ },
1197
+ /**
1198
+ * Records a file change under the active prompt transaction.
1199
+ */
1200
+ async recordFileChange(absolutePath) {
1201
+ if (!currentTransaction) return;
1202
+ const alreadyBackedUp = currentTransaction.changes.some((c) => c.filePath === absolutePath);
1203
+ if (alreadyBackedUp) return;
1204
+ const fileExists = await fs5.pathExists(absolutePath);
1205
+ let type = "create";
1206
+ let backupFile = null;
1207
+ if (fileExists) {
1208
+ type = "update";
1209
+ const fileName = path4.basename(absolutePath);
1210
+ backupFile = `${currentTransaction.id}_${fileName}.bak`;
1211
+ const chatBackupDir = path4.join(BACKUPS_DIR, currentTransaction.chatId);
1212
+ await fs5.ensureDir(chatBackupDir);
1213
+ const backupPath = path4.join(chatBackupDir, backupFile);
1214
+ const content = await fs5.readFile(absolutePath, "utf8");
1215
+ const encrypted = encryptAes(content);
1216
+ await fs5.writeFile(backupPath, encrypted, "utf8");
1217
+ }
1218
+ currentTransaction.changes.push({
1219
+ filePath: absolutePath,
1220
+ type,
1221
+ backupFile
1222
+ });
1223
+ },
1224
+ /**
1225
+ * Finalizes the transaction and saves it to ledger.json.
1226
+ */
1227
+ async commitTransaction() {
1228
+ if (!currentTransaction || currentTransaction.changes.length === 0) {
1229
+ currentTransaction = null;
1230
+ return;
1231
+ }
1232
+ const ledger = readEncryptedJson(LEDGER_FILE, []);
1233
+ ledger.push(currentTransaction);
1234
+ if (ledger.length > 500) {
1235
+ const removed = ledger.shift();
1236
+ if (removed.changes) {
1237
+ for (const change of removed.changes) {
1238
+ if (change.backupFile) {
1239
+ const backupPath = path4.join(BACKUPS_DIR, removed.chatId, change.backupFile);
1240
+ await fs5.remove(backupPath);
1241
+ }
1242
+ }
1243
+ }
1244
+ }
1245
+ writeEncryptedJson(LEDGER_FILE, ledger);
1246
+ currentTransaction = null;
1247
+ },
1248
+ /**
1249
+ * Reverts the codebase to a state immediately before the target transaction.
1250
+ * Reverts the target transaction and all subsequent ones in reverse sequential order.
1251
+ * Returns the target prompt text so it can be loaded back into the user input.
1252
+ */
1253
+ async rollbackToBefore(txId) {
1254
+ const ledger = readEncryptedJson(LEDGER_FILE, null);
1255
+ if (!ledger) throw new Error("No transaction ledger found.");
1256
+ const targetIndex = ledger.findIndex((t) => t.id === txId);
1257
+ if (targetIndex === -1) throw new Error(`Transaction [${txId}] not found.`);
1258
+ const chatId = ledger[targetIndex].chatId;
1259
+ const targetPrompt = ledger[targetIndex].prompt;
1260
+ const toRevert = ledger.slice(targetIndex).filter((t) => t.chatId === chatId && !t.reverted).reverse();
1261
+ for (const tx of toRevert) {
1262
+ for (const change of [...tx.changes].reverse()) {
1263
+ if (change.type === "create") {
1264
+ if (await fs5.pathExists(change.filePath)) {
1265
+ await fs5.remove(change.filePath);
1266
+ }
1267
+ } else if (change.type === "update") {
1268
+ const backupPath = path4.join(BACKUPS_DIR, tx.chatId, change.backupFile);
1269
+ if (await fs5.pathExists(backupPath)) {
1270
+ const encrypted = await fs5.readFile(backupPath, "utf8");
1271
+ const decrypted = decryptAes(encrypted);
1272
+ await fs5.writeFile(change.filePath, decrypted, "utf8");
1273
+ }
1274
+ }
1275
+ }
1276
+ tx.reverted = true;
1277
+ }
1278
+ for (const tx of toRevert) {
1279
+ for (const change of tx.changes) {
1280
+ if (change.backupFile) {
1281
+ const backupPath = path4.join(BACKUPS_DIR, tx.chatId, change.backupFile);
1282
+ await fs5.remove(backupPath);
1283
+ }
1284
+ }
1285
+ }
1286
+ const updatedLedger = ledger.filter((t) => !toRevert.some((r) => r.id === t.id));
1287
+ writeEncryptedJson(LEDGER_FILE, updatedLedger);
1288
+ return {
1289
+ success: true,
1290
+ chatId,
1291
+ targetPrompt
1292
+ };
1293
+ },
1294
+ /**
1295
+ * Gets all non-reverted prompt transactions for a specific chat.
1296
+ */
1297
+ async getChatHistory(chatId) {
1298
+ try {
1299
+ const ledger = readEncryptedJson(LEDGER_FILE, []);
1300
+ return ledger.filter((t) => t.chatId === chatId && !t.reverted);
1301
+ } catch (e) {
1302
+ return [];
1303
+ }
1304
+ },
1305
+ /**
1306
+ * Cleans up all transaction logs and backups associated with a deleted chat.
1307
+ */
1308
+ async deleteChatBackups(chatId) {
1309
+ try {
1310
+ const chatBackupDir = path4.join(BACKUPS_DIR, chatId);
1311
+ await fs5.remove(chatBackupDir);
1312
+ let ledger = readEncryptedJson(LEDGER_FILE, []);
1313
+ const originalLength = ledger.length;
1314
+ ledger = ledger.filter((t) => t.chatId !== chatId);
1315
+ if (ledger.length !== originalLength) {
1316
+ writeEncryptedJson(LEDGER_FILE, ledger);
1317
+ }
1318
+ } catch (e) {
1319
+ }
1320
+ }
1321
+ };
1322
+ }
1323
+ });
1324
+
1325
+ // src/utils/history.js
1326
+ import fs6 from "fs-extra";
1327
+ import path5 from "path";
1171
1328
  import { nanoid } from "nanoid";
1172
1329
  var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, parseCustomDate, cleanupLogFile, cleanupOldLogs, getTruncatedHistory;
1173
1330
  var init_history = __esm({
1174
1331
  "src/utils/history.js"() {
1175
1332
  init_crypto();
1176
1333
  init_paths();
1334
+ init_revert();
1177
1335
  WRITE_LOCK = Promise.resolve();
1178
1336
  withLock = (op) => {
1179
1337
  const nextLock = WRITE_LOCK.then(async () => {
@@ -1189,7 +1347,7 @@ var init_history = __esm({
1189
1347
  return nextLock;
1190
1348
  };
1191
1349
  loadHistory = async () => {
1192
- if (await fs5.pathExists(HISTORY_FILE)) {
1350
+ if (await fs6.pathExists(HISTORY_FILE)) {
1193
1351
  try {
1194
1352
  return readEncryptedJson(HISTORY_FILE, {});
1195
1353
  } catch (e) {
@@ -1239,6 +1397,7 @@ var init_history = __esm({
1239
1397
  delete cache[id];
1240
1398
  writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
1241
1399
  }
1400
+ await RevertManager.deleteChatBackups(id);
1242
1401
  return history;
1243
1402
  });
1244
1403
  };
@@ -1308,8 +1467,8 @@ var init_history = __esm({
1308
1467
  };
1309
1468
  cleanupLogFile = async (filePath) => {
1310
1469
  try {
1311
- if (!await fs5.pathExists(filePath)) return;
1312
- const content = await fs5.readFile(filePath, "utf8");
1470
+ if (!await fs6.pathExists(filePath)) return;
1471
+ const content = await fs6.readFile(filePath, "utf8");
1313
1472
  if (!content.trim()) return;
1314
1473
  const lines = content.split("\n");
1315
1474
  const entries = [];
@@ -1349,26 +1508,26 @@ var init_history = __esm({
1349
1508
  }
1350
1509
  const finalContent = keptEntries.join("\n").trim();
1351
1510
  if (finalContent) {
1352
- await fs5.writeFile(filePath, finalContent + "\n", "utf8");
1511
+ await fs6.writeFile(filePath, finalContent + "\n", "utf8");
1353
1512
  } else {
1354
- await fs5.writeFile(filePath, "", "utf8");
1513
+ await fs6.writeFile(filePath, "", "utf8");
1355
1514
  }
1356
1515
  } catch (e) {
1357
1516
  }
1358
1517
  };
1359
1518
  cleanupOldLogs = async (logsDir) => {
1360
1519
  try {
1361
- if (!await fs5.pathExists(logsDir)) return;
1520
+ if (!await fs6.pathExists(logsDir)) return;
1362
1521
  const cleanRecursive = async (dir) => {
1363
- const files = await fs5.readdir(dir);
1522
+ const files = await fs6.readdir(dir);
1364
1523
  for (const file of files) {
1365
- const fullPath = path4.join(dir, file);
1366
- const stat = await fs5.stat(fullPath);
1524
+ const fullPath = path5.join(dir, file);
1525
+ const stat = await fs6.stat(fullPath);
1367
1526
  if (stat.isDirectory()) {
1368
1527
  await cleanRecursive(fullPath);
1369
- const subFiles = await fs5.readdir(fullPath);
1528
+ const subFiles = await fs6.readdir(fullPath);
1370
1529
  if (subFiles.length === 0) {
1371
- await fs5.remove(fullPath);
1530
+ await fs6.remove(fullPath);
1372
1531
  }
1373
1532
  } else if (file.endsWith(".log")) {
1374
1533
  await cleanupLogFile(fullPath);
@@ -1391,8 +1550,8 @@ var init_history = __esm({
1391
1550
  });
1392
1551
 
1393
1552
  // src/utils/usage.js
1394
- import fs6 from "fs-extra";
1395
- import path5 from "path";
1553
+ import fs7 from "fs-extra";
1554
+ import path6 from "path";
1396
1555
  import os3 from "os";
1397
1556
  var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, incrementUsage, addToUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
1398
1557
  var init_usage = __esm({
@@ -1401,14 +1560,14 @@ var init_usage = __esm({
1401
1560
  init_crypto();
1402
1561
  getLocalBackupPath = () => {
1403
1562
  if (process.platform === "win32") {
1404
- const localAppData = process.env.LOCALAPPDATA || path5.join(os3.homedir(), "AppData", "Local");
1405
- return path5.join(localAppData, "FxFl", "backups", "backup.json");
1563
+ const localAppData = process.env.LOCALAPPDATA || path6.join(os3.homedir(), "AppData", "Local");
1564
+ return path6.join(localAppData, "FxFl", "backups", "backup.json");
1406
1565
  }
1407
1566
  if (process.platform === "darwin") {
1408
- return path5.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
1567
+ return path6.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
1409
1568
  }
1410
- const xdgDataHome = process.env.XDG_DATA_HOME || path5.join(os3.homedir(), ".local", "share");
1411
- return path5.join(xdgDataHome, "fxfl", "backups", "backup.json");
1569
+ const xdgDataHome = process.env.XDG_DATA_HOME || path6.join(os3.homedir(), ".local", "share");
1570
+ return path6.join(xdgDataHome, "fxfl", "backups", "backup.json");
1412
1571
  };
1413
1572
  BACKUP_FILE = getLocalBackupPath();
1414
1573
  generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
@@ -1433,8 +1592,8 @@ var init_usage = __esm({
1433
1592
  let primaryData = null;
1434
1593
  let backupData = null;
1435
1594
  try {
1436
- if (await fs6.exists(tempFile)) {
1437
- const rawContent = (await fs6.readFile(tempFile, "utf8")).trim();
1595
+ if (await fs7.exists(tempFile)) {
1596
+ const rawContent = (await fs7.readFile(tempFile, "utf8")).trim();
1438
1597
  let parsed = null;
1439
1598
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1440
1599
  parsed = JSON.parse(rawContent);
@@ -1444,26 +1603,26 @@ var init_usage = __esm({
1444
1603
  if (parsed && parsed.date && parsed.stats) {
1445
1604
  primaryData = parsed;
1446
1605
  try {
1447
- await fs6.rename(tempFile, USAGE_FILE);
1606
+ await fs7.rename(tempFile, USAGE_FILE);
1448
1607
  } catch (e) {
1449
1608
  }
1450
1609
  } else {
1451
1610
  try {
1452
- await fs6.remove(tempFile);
1611
+ await fs7.remove(tempFile);
1453
1612
  } catch (e) {
1454
1613
  }
1455
1614
  }
1456
1615
  }
1457
1616
  } catch (err) {
1458
1617
  try {
1459
- await fs6.remove(tempFile);
1618
+ await fs7.remove(tempFile);
1460
1619
  } catch (e) {
1461
1620
  }
1462
1621
  }
1463
1622
  if (!primaryData) {
1464
1623
  try {
1465
- if (await fs6.exists(USAGE_FILE)) {
1466
- const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1624
+ if (await fs7.exists(USAGE_FILE)) {
1625
+ const rawContent = (await fs7.readFile(USAGE_FILE, "utf8")).trim();
1467
1626
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1468
1627
  primaryData = JSON.parse(rawContent);
1469
1628
  } else {
@@ -1474,8 +1633,8 @@ var init_usage = __esm({
1474
1633
  }
1475
1634
  }
1476
1635
  try {
1477
- if (await fs6.exists(BACKUP_FILE)) {
1478
- const rawContent = (await fs6.readFile(BACKUP_FILE, "utf8")).trim();
1636
+ if (await fs7.exists(BACKUP_FILE)) {
1637
+ const rawContent = (await fs7.readFile(BACKUP_FILE, "utf8")).trim();
1479
1638
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1480
1639
  backupData = JSON.parse(rawContent);
1481
1640
  } else {
@@ -1489,8 +1648,8 @@ var init_usage = __esm({
1489
1648
  if (primaryData.saveId !== backupData.saveId) {
1490
1649
  resolvedData = primaryData;
1491
1650
  try {
1492
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1493
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1651
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1652
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1494
1653
  } catch (e) {
1495
1654
  }
1496
1655
  } else {
@@ -1499,15 +1658,15 @@ var init_usage = __esm({
1499
1658
  } else if (primaryData && !backupData) {
1500
1659
  resolvedData = primaryData;
1501
1660
  try {
1502
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1503
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1661
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1662
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1504
1663
  } catch (e) {
1505
1664
  }
1506
1665
  } else if (!primaryData && backupData) {
1507
1666
  resolvedData = backupData;
1508
1667
  try {
1509
- await fs6.ensureDir(path5.dirname(USAGE_FILE));
1510
- await fs6.copy(BACKUP_FILE, USAGE_FILE);
1668
+ await fs7.ensureDir(path6.dirname(USAGE_FILE));
1669
+ await fs7.copy(BACKUP_FILE, USAGE_FILE);
1511
1670
  } catch (e) {
1512
1671
  }
1513
1672
  }
@@ -1526,11 +1685,11 @@ var init_usage = __esm({
1526
1685
  flushUsage = async () => {
1527
1686
  if (!isDirty || !cachedUsage) return;
1528
1687
  try {
1529
- await fs6.ensureDir(path5.dirname(USAGE_FILE));
1688
+ await fs7.ensureDir(path6.dirname(USAGE_FILE));
1530
1689
  let diskData = null;
1531
1690
  try {
1532
- if (await fs6.exists(USAGE_FILE)) {
1533
- const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1691
+ if (await fs7.exists(USAGE_FILE)) {
1692
+ const rawContent = (await fs7.readFile(USAGE_FILE, "utf8")).trim();
1534
1693
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1535
1694
  diskData = JSON.parse(rawContent);
1536
1695
  } else {
@@ -1561,14 +1720,14 @@ var init_usage = __esm({
1561
1720
  cachedUsage.saveId = generateSaveId();
1562
1721
  const tempFile = USAGE_FILE + ".tmp";
1563
1722
  const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
1564
- await fs6.writeFile(tempFile, encryptedStr, "utf8");
1565
- const fd = await fs6.open(tempFile, "r+");
1566
- await fs6.fsync(fd);
1567
- await fs6.close(fd);
1568
- await fs6.rename(tempFile, USAGE_FILE);
1723
+ await fs7.writeFile(tempFile, encryptedStr, "utf8");
1724
+ const fd = await fs7.open(tempFile, "r+");
1725
+ await fs7.fsync(fd);
1726
+ await fs7.close(fd);
1727
+ await fs7.rename(tempFile, USAGE_FILE);
1569
1728
  try {
1570
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1571
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1729
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1730
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1572
1731
  } catch (backupErr) {
1573
1732
  }
1574
1733
  isDirty = false;
@@ -2221,8 +2380,8 @@ var init_chat = __esm({
2221
2380
  });
2222
2381
 
2223
2382
  // src/tools/view_file.js
2224
- import fs7 from "fs";
2225
- import path6 from "path";
2383
+ import fs8 from "fs";
2384
+ import path7 from "path";
2226
2385
  var view_file;
2227
2386
  var init_view_file = __esm({
2228
2387
  "src/tools/view_file.js"() {
@@ -2234,16 +2393,16 @@ var init_view_file = __esm({
2234
2393
  const finalStart = sLine || 1;
2235
2394
  const finalEnd = eLine || (sLine ? sLine + 800 : 800);
2236
2395
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
2237
- const absolutePath = path6.resolve(process.cwd(), targetPath);
2396
+ const absolutePath = path7.resolve(process.cwd(), targetPath);
2238
2397
  try {
2239
- if (!fs7.existsSync(absolutePath)) {
2398
+ if (!fs8.existsSync(absolutePath)) {
2240
2399
  return `ERROR: File [${targetPath}] does not exist.`;
2241
2400
  }
2242
- const stats = fs7.statSync(absolutePath);
2401
+ const stats = fs8.statSync(absolutePath);
2243
2402
  if (stats.isDirectory()) {
2244
2403
  return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
2245
2404
  }
2246
- const ext = path6.extname(targetPath).toLowerCase();
2405
+ const ext = path7.extname(targetPath).toLowerCase();
2247
2406
  const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
2248
2407
  if (videoExtensions.includes(ext)) {
2249
2408
  const format = ext.slice(1).toUpperCase();
@@ -2259,7 +2418,7 @@ var init_view_file = __esm({
2259
2418
  ".doc": "application/msword"
2260
2419
  };
2261
2420
  if (mimeMap[ext]) {
2262
- const buffer = fs7.readFileSync(absolutePath);
2421
+ const buffer = fs8.readFileSync(absolutePath);
2263
2422
  const base64 = buffer.toString("base64");
2264
2423
  const mimeType = mimeMap[ext];
2265
2424
  return {
@@ -2272,7 +2431,7 @@ var init_view_file = __esm({
2272
2431
  }
2273
2432
  };
2274
2433
  }
2275
- let content = fs7.readFileSync(absolutePath, "utf8");
2434
+ let content = fs8.readFileSync(absolutePath, "utf8");
2276
2435
  if (content.startsWith("\uFEFF")) {
2277
2436
  content = content.slice(1);
2278
2437
  }
@@ -2295,24 +2454,26 @@ ${code}`;
2295
2454
  });
2296
2455
 
2297
2456
  // src/tools/write_file.js
2298
- import fs8 from "fs";
2299
- import path7 from "path";
2457
+ import fs9 from "fs";
2458
+ import path8 from "path";
2300
2459
  var write_file;
2301
2460
  var init_write_file = __esm({
2302
2461
  "src/tools/write_file.js"() {
2303
2462
  init_arg_parser();
2463
+ init_revert();
2304
2464
  write_file = async (args) => {
2305
2465
  let { path: targetPath, content } = parseArgs(args);
2306
2466
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
2307
2467
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
2308
2468
  content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2309
- const absolutePath = path7.resolve(process.cwd(), targetPath);
2310
- const parentDir = path7.dirname(absolutePath);
2469
+ const absolutePath = path8.resolve(process.cwd(), targetPath);
2470
+ const parentDir = path8.dirname(absolutePath);
2311
2471
  try {
2472
+ await RevertManager.recordFileChange(absolutePath);
2312
2473
  let ancestry = "";
2313
- if (fs8.existsSync(absolutePath)) {
2474
+ if (fs9.existsSync(absolutePath)) {
2314
2475
  try {
2315
- const oldData = fs8.readFileSync(absolutePath, "utf8");
2476
+ const oldData = fs9.readFileSync(absolutePath, "utf8");
2316
2477
  const lines = oldData.split(/\r?\n/);
2317
2478
  ancestry = `Old File contents:
2318
2479
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
@@ -2324,15 +2485,15 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
2324
2485
  `;
2325
2486
  }
2326
2487
  }
2327
- if (!fs8.existsSync(parentDir)) {
2328
- fs8.mkdirSync(parentDir, { recursive: true });
2488
+ if (!fs9.existsSync(parentDir)) {
2489
+ fs9.mkdirSync(parentDir, { recursive: true });
2329
2490
  }
2330
2491
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2331
2492
  const processedContent = strip(content);
2332
2493
  const lineCount = processedContent.split(/\r?\n/).length;
2333
2494
  const originalSize = Buffer.byteLength(processedContent, "utf8");
2334
- fs8.writeFileSync(absolutePath, processedContent, "utf8");
2335
- let verifiedContent = fs8.readFileSync(absolutePath, "utf8");
2495
+ fs9.writeFileSync(absolutePath, processedContent, "utf8");
2496
+ let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
2336
2497
  const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
2337
2498
  const verifiedLines = verifiedContent.split(/\r?\n/);
2338
2499
  const verifiedLineCount = verifiedLines.length;
@@ -2368,32 +2529,37 @@ Check if Starting and Ending matches your write.`;
2368
2529
  });
2369
2530
 
2370
2531
  // src/tools/update_file.js
2371
- import fs9 from "fs";
2372
- import path8 from "path";
2532
+ import fs10 from "fs";
2533
+ import path9 from "path";
2373
2534
  var update_file;
2374
2535
  var init_update_file = __esm({
2375
2536
  "src/tools/update_file.js"() {
2376
2537
  init_arg_parser();
2538
+ init_revert();
2377
2539
  update_file = async (args) => {
2378
- let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
2540
+ const parsed = parseArgs(args);
2541
+ const targetPath = parsed.path;
2542
+ let content_to_replace = parsed.content_to_replace !== void 0 ? parsed.content_to_replace : parsed.replaceContent;
2543
+ let content_to_add = parsed.content_to_add !== void 0 ? parsed.content_to_add : parsed.newContent;
2379
2544
  if (!targetPath) return 'ERROR: Missing "path" argument for update_file.';
2380
- if (content_to_replace === void 0) return 'ERROR: Missing "content_to_replace" argument.';
2381
- if (content_to_add === void 0) return 'ERROR: Missing "content_to_add" argument.';
2545
+ if (content_to_replace === void 0) return 'ERROR: Missing "replaceContent" argument.';
2546
+ if (content_to_add === void 0) return 'ERROR: Missing "newContent" argument.';
2382
2547
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2383
2548
  content_to_replace = strip(content_to_replace);
2384
2549
  content_to_add = strip(content_to_add);
2385
- const absolutePath = path8.resolve(process.cwd(), targetPath);
2550
+ const absolutePath = path9.resolve(process.cwd(), targetPath);
2386
2551
  try {
2387
- if (!fs9.existsSync(absolutePath)) {
2552
+ if (!fs10.existsSync(absolutePath)) {
2388
2553
  return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
2389
2554
  }
2390
- let diskContent = fs9.readFileSync(absolutePath, "utf8");
2555
+ await RevertManager.recordFileChange(absolutePath);
2556
+ let diskContent = fs10.readFileSync(absolutePath, "utf8");
2391
2557
  if (diskContent.startsWith("\uFEFF")) {
2392
2558
  diskContent = diskContent.slice(1);
2393
2559
  }
2394
2560
  const normalizedDisk = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2395
2561
  if (diskContent !== normalizedDisk) {
2396
- fs9.writeFileSync(absolutePath, normalizedDisk, "utf8");
2562
+ fs10.writeFileSync(absolutePath, normalizedDisk, "utf8");
2397
2563
  diskContent = normalizedDisk;
2398
2564
  }
2399
2565
  const currentContent = diskContent;
@@ -2462,7 +2628,7 @@ var init_update_file = __esm({
2462
2628
  const firstLeadingContext = currentContent.substring(firstLineStart, startPos);
2463
2629
  const finalContentToAdd = adjustIndentation(content_to_add, firstMatchContent, firstLeadingContext);
2464
2630
  const finalContentToReplace = firstMatchContent;
2465
- fs9.writeFileSync(absolutePath, newFileContent, "utf8");
2631
+ fs10.writeFileSync(absolutePath, newFileContent, "utf8");
2466
2632
  const allOriginalLines = currentContent.split(/\r?\n/);
2467
2633
  const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
2468
2634
  const oldLines = content_to_replace.split(/\r?\n/);
@@ -2725,34 +2891,34 @@ ${finalOutput}`);
2725
2891
  });
2726
2892
 
2727
2893
  // src/tools/read_folder.js
2728
- import fs10 from "fs";
2729
- import path9 from "path";
2894
+ import fs11 from "fs";
2895
+ import path10 from "path";
2730
2896
  var read_folder;
2731
2897
  var init_read_folder = __esm({
2732
2898
  "src/tools/read_folder.js"() {
2733
2899
  init_arg_parser();
2734
2900
  read_folder = async (args) => {
2735
2901
  const { path: targetPath = "." } = parseArgs(args);
2736
- const absolutePath = path9.resolve(process.cwd(), targetPath);
2902
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
2737
2903
  try {
2738
- if (!fs10.existsSync(absolutePath)) {
2904
+ if (!fs11.existsSync(absolutePath)) {
2739
2905
  return `ERROR: Path [${targetPath}] does not exist.`;
2740
2906
  }
2741
- const stats = fs10.statSync(absolutePath);
2907
+ const stats = fs11.statSync(absolutePath);
2742
2908
  if (!stats.isDirectory()) {
2743
2909
  return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
2744
2910
  }
2745
- const files = fs10.readdirSync(absolutePath);
2911
+ const files = fs11.readdirSync(absolutePath);
2746
2912
  const totalItems = files.length;
2747
2913
  const maxDisplay = 100;
2748
2914
  const displayItems = files.slice(0, maxDisplay);
2749
2915
  const folderData = [];
2750
2916
  for (const file of displayItems) {
2751
- const fPath = path9.join(absolutePath, file);
2917
+ const fPath = path10.join(absolutePath, file);
2752
2918
  let indicator = "\u{1F4C4}";
2753
2919
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
2754
2920
  try {
2755
- const fStats = fs10.statSync(fPath);
2921
+ const fStats = fs11.statSync(fPath);
2756
2922
  info = {
2757
2923
  name: file,
2758
2924
  type: fStats.isDirectory() ? "directory" : "file",
@@ -2835,13 +3001,14 @@ var init_ask_user = __esm({
2835
3001
 
2836
3002
  // src/tools/write_pdf.js
2837
3003
  import puppeteer3 from "puppeteer";
2838
- import path10 from "path";
2839
- import fs11 from "fs-extra";
3004
+ import path11 from "path";
3005
+ import fs12 from "fs-extra";
2840
3006
  import { PDFDocument } from "pdf-lib";
2841
3007
  var write_pdf;
2842
3008
  var init_write_pdf = __esm({
2843
3009
  "src/tools/write_pdf.js"() {
2844
3010
  init_arg_parser();
3011
+ init_revert();
2845
3012
  write_pdf = async (args) => {
2846
3013
  const {
2847
3014
  path: targetPath,
@@ -2851,10 +3018,11 @@ var init_write_pdf = __esm({
2851
3018
  } = parseArgs(args);
2852
3019
  if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
2853
3020
  if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
2854
- const absolutePath = path10.resolve(process.cwd(), targetPath);
3021
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
2855
3022
  let browser = null;
2856
3023
  try {
2857
- await fs11.ensureDir(path10.dirname(absolutePath));
3024
+ await fs12.ensureDir(path11.dirname(absolutePath));
3025
+ await RevertManager.recordFileChange(absolutePath);
2858
3026
  browser = await puppeteer3.launch({
2859
3027
  headless: true,
2860
3028
  args: [
@@ -2872,11 +3040,11 @@ var init_write_pdf = __esm({
2872
3040
  return null;
2873
3041
  }
2874
3042
  try {
2875
- const imgPath = path10.resolve(process.cwd(), originalSrc);
2876
- if (await fs11.pathExists(imgPath)) {
2877
- const ext = path10.extname(imgPath).toLowerCase().replace(".", "") || "png";
3043
+ const imgPath = path11.resolve(process.cwd(), originalSrc);
3044
+ if (await fs12.pathExists(imgPath)) {
3045
+ const ext = path11.extname(imgPath).toLowerCase().replace(".", "") || "png";
2878
3046
  const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
2879
- const base64 = await fs11.readFile(imgPath, "base64");
3047
+ const base64 = await fs12.readFile(imgPath, "base64");
2880
3048
  return `data:image/${mime};base64,${base64}`;
2881
3049
  }
2882
3050
  } catch (e) {
@@ -2891,9 +3059,9 @@ var init_write_pdf = __esm({
2891
3059
  const fullTag = match[0];
2892
3060
  if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
2893
3061
  try {
2894
- const cssPath = path10.resolve(process.cwd(), originalHref);
2895
- if (await fs11.pathExists(cssPath)) {
2896
- const cssContent = await fs11.readFile(cssPath, "utf-8");
3062
+ const cssPath = path11.resolve(process.cwd(), originalHref);
3063
+ if (await fs12.pathExists(cssPath)) {
3064
+ const cssContent = await fs12.readFile(cssPath, "utf-8");
2897
3065
  cssCache[fullTag] = `<style>${cssContent}</style>`;
2898
3066
  }
2899
3067
  } catch (e) {
@@ -2974,7 +3142,7 @@ var init_write_pdf = __esm({
2974
3142
  printBackground: true
2975
3143
  });
2976
3144
  const pdfDoc = await PDFDocument.load(pdfBytes);
2977
- const fileName = path10.basename(targetPath);
3145
+ const fileName = path11.basename(targetPath);
2978
3146
  pdfDoc.setTitle(`FluxFlow_${fileName}`);
2979
3147
  pdfDoc.setAuthor("FluxFlow CLI");
2980
3148
  pdfDoc.setSubject("Generated with Agentic AI System");
@@ -2982,8 +3150,8 @@ var init_write_pdf = __esm({
2982
3150
  pdfDoc.setCreator("FluxFlow PDF Engine");
2983
3151
  pdfDoc.setProducer("FluxFlow (Generative AI)");
2984
3152
  const finalPdfBytes = await pdfDoc.save();
2985
- await fs11.writeFile(absolutePath, finalPdfBytes);
2986
- const stats = await fs11.stat(absolutePath);
3153
+ await fs12.writeFile(absolutePath, finalPdfBytes);
3154
+ const stats = await fs12.stat(absolutePath);
2987
3155
  return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
2988
3156
  } catch (err) {
2989
3157
  return `ERROR: Failed to generate PDF [${targetPath}]: ${err.message}`;
@@ -2995,13 +3163,14 @@ var init_write_pdf = __esm({
2995
3163
  });
2996
3164
 
2997
3165
  // src/tools/write_docx.js
2998
- import fs12 from "fs-extra";
2999
- import path11 from "path";
3166
+ import fs13 from "fs-extra";
3167
+ import path12 from "path";
3000
3168
  import HTMLtoDOCX from "html-to-docx";
3001
3169
  var write_docx;
3002
3170
  var init_write_docx = __esm({
3003
3171
  "src/tools/write_docx.js"() {
3004
3172
  init_arg_parser();
3173
+ init_revert();
3005
3174
  write_docx = async (args) => {
3006
3175
  const {
3007
3176
  path: targetPath,
@@ -3009,10 +3178,11 @@ var init_write_docx = __esm({
3009
3178
  } = parseArgs(args);
3010
3179
  if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
3011
3180
  if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
3012
- const absolutePath = path11.resolve(process.cwd(), targetPath);
3181
+ const absolutePath = path12.resolve(process.cwd(), targetPath);
3013
3182
  try {
3014
- await fs12.ensureDir(path11.dirname(absolutePath));
3015
- const fileName = path11.basename(targetPath);
3183
+ await fs13.ensureDir(path12.dirname(absolutePath));
3184
+ await RevertManager.recordFileChange(absolutePath);
3185
+ const fileName = path12.basename(targetPath);
3016
3186
  const fullHtml = content.includes("<html") ? content : `
3017
3187
  <!DOCTYPE html>
3018
3188
  <html lang="en">
@@ -3033,7 +3203,7 @@ var init_write_docx = __esm({
3033
3203
  footer: true,
3034
3204
  pageNumber: true
3035
3205
  });
3036
- await fs12.writeFile(absolutePath, docxBuffer);
3206
+ await fs13.writeFile(absolutePath, docxBuffer);
3037
3207
  return `SUCCESS: Word document [${targetPath}] generated successfully.
3038
3208
  - Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
3039
3209
  } catch (err) {
@@ -3100,8 +3270,8 @@ var init_search_keyword = __esm({
3100
3270
  });
3101
3271
 
3102
3272
  // src/utils/settings.js
3103
- import fs13 from "fs-extra";
3104
- import path12 from "path";
3273
+ import fs14 from "fs-extra";
3274
+ import path13 from "path";
3105
3275
  var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
3106
3276
  var init_settings = __esm({
3107
3277
  "src/utils/settings.js"() {
@@ -3143,7 +3313,7 @@ var init_settings = __esm({
3143
3313
  loadSettings = async () => {
3144
3314
  let settingsObj = { ...DEFAULT_SETTINGS };
3145
3315
  try {
3146
- if (await fs13.exists(SETTINGS_FILE)) {
3316
+ if (await fs14.exists(SETTINGS_FILE)) {
3147
3317
  const saved = readAesEncryptedJson(SETTINGS_FILE);
3148
3318
  if (saved.imageSettings && saved.imageSettings.apiKey) {
3149
3319
  try {
@@ -3188,12 +3358,12 @@ var init_settings = __esm({
3188
3358
  const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
3189
3359
  const folders = ["logs", "secret"];
3190
3360
  for (const folder of folders) {
3191
- const src = path12.join(FLUXFLOW_DIR2, folder);
3192
- const dest = path12.join(newPath, folder);
3361
+ const src = path13.join(FLUXFLOW_DIR2, folder);
3362
+ const dest = path13.join(newPath, folder);
3193
3363
  try {
3194
- if (await fs13.exists(src)) {
3195
- await fs13.ensureDir(dest);
3196
- await fs13.copy(src, dest, { overwrite: true });
3364
+ if (await fs14.exists(src)) {
3365
+ await fs14.ensureDir(dest);
3366
+ await fs14.copy(src, dest, { overwrite: true });
3197
3367
  }
3198
3368
  } catch (err) {
3199
3369
  console.error(`Migration failed for ${folder}:`, err);
@@ -3219,7 +3389,7 @@ var init_settings = __esm({
3219
3389
  if (updated.imageSettings) {
3220
3390
  updated.imageSettings = { ...updated.imageSettings, apiKey: "" };
3221
3391
  }
3222
- await fs13.ensureDir(path12.dirname(SETTINGS_FILE));
3392
+ await fs14.ensureDir(path13.dirname(SETTINGS_FILE));
3223
3393
  writeAesEncryptedJson(SETTINGS_FILE, updated);
3224
3394
  return true;
3225
3395
  } catch (err) {
@@ -3239,8 +3409,8 @@ var init_fallback_key = __esm({
3239
3409
  });
3240
3410
 
3241
3411
  // src/tools/generate_image.js
3242
- import fs14 from "fs-extra";
3243
- import path13 from "path";
3412
+ import fs15 from "fs-extra";
3413
+ import path14 from "path";
3244
3414
  var injectPngMetadata, generate_image;
3245
3415
  var init_generate_image = __esm({
3246
3416
  "src/tools/generate_image.js"() {
@@ -3248,6 +3418,7 @@ var init_generate_image = __esm({
3248
3418
  init_settings();
3249
3419
  init_usage();
3250
3420
  init_fallback_key();
3421
+ init_revert();
3251
3422
  injectPngMetadata = (buffer, metadata = {}) => {
3252
3423
  try {
3253
3424
  if (buffer.length < 8 || buffer[0] !== 137 || buffer[1] !== 80 || buffer[2] !== 78 || buffer[3] !== 71) {
@@ -3419,9 +3590,10 @@ var init_generate_image = __esm({
3419
3590
  "Seed": String(seed)
3420
3591
  };
3421
3592
  finalBuffer = injectPngMetadata(finalBuffer, metadata);
3422
- const absolutePath = path13.resolve(process.cwd(), outputPath);
3423
- await fs14.ensureDir(path13.dirname(absolutePath));
3424
- await fs14.writeFile(absolutePath, finalBuffer);
3593
+ const absolutePath = path14.resolve(process.cwd(), outputPath);
3594
+ await fs15.ensureDir(path14.dirname(absolutePath));
3595
+ await RevertManager.recordFileChange(absolutePath);
3596
+ await fs15.writeFile(absolutePath, finalBuffer);
3425
3597
  await recordImageGeneration(settings);
3426
3598
  return `SUCCESS: Image successfully generated from prompt [${prompt}] and saved to [${outputPath}].`;
3427
3599
  } catch (err) {
@@ -3590,8 +3762,8 @@ var init_tools = __esm({
3590
3762
 
3591
3763
  // src/utils/ai.js
3592
3764
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
3593
- import path14 from "path";
3594
- import fs15 from "fs";
3765
+ import path15 from "path";
3766
+ import fs16 from "fs";
3595
3767
  var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, consolidatePastMemories, getAIStream;
3596
3768
  var init_ai = __esm({
3597
3769
  "src/utils/ai.js"() {
@@ -3603,6 +3775,7 @@ var init_ai = __esm({
3603
3775
  init_arg_parser();
3604
3776
  init_terminal();
3605
3777
  init_paths();
3778
+ init_revert();
3606
3779
  client = null;
3607
3780
  TERMINATION_SIGNAL = false;
3608
3781
  signalTermination = () => {
@@ -3627,7 +3800,7 @@ var init_ai = __esm({
3627
3800
  try {
3628
3801
  const pArgs = parseArgs(argsStr);
3629
3802
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
3630
- return filePath ? path14.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3803
+ return filePath ? path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3631
3804
  } catch (e) {
3632
3805
  return null;
3633
3806
  }
@@ -3754,16 +3927,15 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3754
3927
  }
3755
3928
  const toolContext = { chatId, sessionId: chatId, history };
3756
3929
  const result = await dispatchTool(toolName, janitorToolCall.args, toolContext);
3757
- const date = (/* @__PURE__ */ new Date()).toLocaleString();
3758
- const janitorLogDir = path14.join(LOGS_DIR, "janitor");
3759
- fs15.appendFileSync(path14.join(janitorLogDir, "debug.log"), `DEBUG [${date}]: RESULT [${toolName}]: ${result}
3760
- `);
3761
- if (toolName.toLowerCase() === "memory" && !janitorToolCall.args.includes("action='temp'")) {
3762
- if (onMemoryUpdated) onMemoryUpdated();
3763
- if (process.stdout.isTTY) {
3764
- process.stdout.write(`\x1B]0;Memory Updated\x07`);
3930
+ if (toolName.toLowerCase() === "memory") {
3931
+ const isUserAction = janitorToolCall.args.includes("action='user'") || janitorToolCall.args.includes('action="user"');
3932
+ if (isUserAction && !result.startsWith("ERROR")) {
3933
+ if (onMemoryUpdated) onMemoryUpdated();
3934
+ if (process.stdout.isTTY) {
3935
+ process.stdout.write(`\x1B]0;Memory Updated\x07`);
3936
+ }
3937
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
3765
3938
  }
3766
- await new Promise((resolve) => setTimeout(resolve, 3e3));
3767
3939
  }
3768
3940
  }
3769
3941
  if (!scoreToolCalled) {
@@ -3795,9 +3967,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3795
3967
  process.stdout.write(`\x1B]0;Finalizing Error\x07`);
3796
3968
  }
3797
3969
  await new Promise((resolve) => setTimeout(resolve, 1e3));
3798
- const janitorErrDir = path14.join(LOGS_DIR, "janitor");
3799
- if (!fs15.existsSync(janitorErrDir)) fs15.mkdirSync(janitorErrDir, { recursive: true });
3800
- fs15.appendFileSync(path14.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
3970
+ const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3971
+ if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
3972
+ fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
3801
3973
 
3802
3974
  `);
3803
3975
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -3806,8 +3978,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3806
3978
  }
3807
3979
  }
3808
3980
  if (attempts) {
3809
- const janitorErrDir = path14.join(LOGS_DIR, "janitor");
3810
- fs15.appendFileSync(path14.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3981
+ const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3982
+ fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3811
3983
 
3812
3984
 
3813
3985
  `);
@@ -4108,10 +4280,10 @@ ${newMemoryListStr}
4108
4280
  }
4109
4281
  }
4110
4282
  } catch (err) {
4111
- const janitorLogDir = path14.join(LOGS_DIR, "janitor");
4112
- if (!fs15.existsSync(janitorLogDir)) fs15.mkdirSync(janitorLogDir, { recursive: true });
4113
- fs15.appendFileSync(
4114
- path14.join(janitorLogDir, "error.log"),
4283
+ const janitorLogDir = path15.join(LOGS_DIR, "janitor");
4284
+ if (!fs16.existsSync(janitorLogDir)) fs16.mkdirSync(janitorLogDir, { recursive: true });
4285
+ fs16.appendFileSync(
4286
+ path15.join(janitorLogDir, "error.log"),
4115
4287
  `[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${err.message}
4116
4288
  `
4117
4289
  );
@@ -4125,340 +4297,322 @@ ${newMemoryListStr}
4125
4297
  const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
4126
4298
  const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
4127
4299
  const needTitle = isFirstPrompt || hasTitleSignal;
4128
- const agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
4129
- let modifiedHistory = [...history.slice(0, -1)];
4130
- if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
4131
- modifiedHistory = getTruncatedHistory(modifiedHistory, 6);
4132
- }
4133
- if (isFirstPrompt && isMemoryEnabled) {
4134
- yield { type: "status", content: "Condensing past chat memories..." };
4135
- await consolidatePastMemories(chatId, settings);
4136
- }
4137
- const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
4138
- const cacheStorage = readEncryptedJson(TEMP_MEM_CHAT_FILE, {});
4139
- const otherRawMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems);
4140
- const cachedSummaries = Object.entries(cacheStorage).filter(([id]) => id !== chatId).slice(-20).map(([id, summary]) => `[Chat Summary]: ${summary}`);
4141
- const otherMemories = [...cachedSummaries, ...otherRawMemories].map((mem) => `- ${mem}`).join("\n");
4142
- const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
4143
- const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
4144
- const isContext32k = (sessionStats?.tokens || 0) >= 32e3;
4145
- const memoryPrompt = getMemoryPrompt(otherMemories, mainUserMemories, isMemoryEnabled, isContext32k);
4146
- const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: true });
4147
- const firstUserMsg = `${memoryPrompt}
4148
- [METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
4149
- ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CORE PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**\n" : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
4150
- modifiedHistory.push({ role: "user", text: firstUserMsg });
4151
- let lastUsage = null;
4152
- const MAX_LOOPS = mode === "Flux" ? 70 : 7;
4153
- const MAX_RETRIES = 16;
4154
- yield { type: "status", content: "Connecting..." };
4155
- TERMINATION_SIGNAL = false;
4156
- let fullAgentResponseChunks = [];
4157
- let wasToolCalledInLastLoop = false;
4158
- modifiedHistory.forEach((msg) => {
4159
- if (msg.text && msg.role === "agent") {
4160
- msg.text = msg.text.replace(/<(think|thought)>[\s\S]*?<\/(think|thought)>/gi, "").trim();
4161
- }
4162
- });
4163
- for (let loop = 0; loop <= MAX_LOOPS; loop++) {
4164
- if (loop > 0) {
4165
- yield { type: "status", content: "Processed. Reconnecting..." };
4300
+ let agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
4301
+ agentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
4302
+ await RevertManager.startTransaction(chatId, agentText);
4303
+ try {
4304
+ let modifiedHistory = [...history.slice(0, -1)];
4305
+ if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
4306
+ modifiedHistory = getTruncatedHistory(modifiedHistory, 6);
4166
4307
  }
4167
- if (TERMINATION_SIGNAL) {
4168
- yield { type: "status", content: "Termination Signal Received." };
4169
- await new Promise((resolve) => setTimeout(resolve, 1500));
4170
- break;
4308
+ if (isFirstPrompt && isMemoryEnabled) {
4309
+ yield { type: "status", content: "Condensing past chat memories..." };
4310
+ await consolidatePastMemories(chatId, settings);
4171
4311
  }
4172
- if (steeringCallback) {
4173
- const hint = await steeringCallback();
4174
- if (hint) {
4175
- if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
4176
- modifiedHistory[modifiedHistory.length - 1].text += `
4312
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
4313
+ const cacheStorage = readEncryptedJson(TEMP_MEM_CHAT_FILE, {});
4314
+ const otherRawMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems);
4315
+ const cachedSummaries = Object.entries(cacheStorage).filter(([id]) => id !== chatId).slice(-20).map(([id, summary]) => `[Chat Summary]: ${summary}`);
4316
+ const otherMemories = [...cachedSummaries, ...otherRawMemories].map((mem) => `- ${mem}`).join("\n");
4317
+ const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
4318
+ const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
4319
+ const isContext32k = (sessionStats?.tokens || 0) >= 32e3;
4320
+ const memoryPrompt = getMemoryPrompt(otherMemories, mainUserMemories, isMemoryEnabled, isContext32k);
4321
+ const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: true });
4322
+ const firstUserMsg = `${memoryPrompt}
4323
+ [METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
4324
+ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CORE PRIORITY. DO NOT START A RESPONSE WITHOUT <think> ... </think>**\n" : ""}[USER] ${agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim()}`.trim();
4325
+ modifiedHistory.push({ role: "user", text: firstUserMsg });
4326
+ let lastUsage = null;
4327
+ const MAX_LOOPS = mode === "Flux" ? 70 : 7;
4328
+ const MAX_RETRIES = 16;
4329
+ yield { type: "status", content: "Connecting..." };
4330
+ TERMINATION_SIGNAL = false;
4331
+ let fullAgentResponseChunks = [];
4332
+ let wasToolCalledInLastLoop = false;
4333
+ modifiedHistory.forEach((msg) => {
4334
+ if (msg.text && msg.role === "agent") {
4335
+ msg.text = msg.text.replace(/<(think|thought)>[\s\S]*?<\/(think|thought)>/gi, "").trim();
4336
+ }
4337
+ });
4338
+ for (let loop = 0; loop <= MAX_LOOPS; loop++) {
4339
+ if (loop > 0) {
4340
+ yield { type: "status", content: "Processed. Reconnecting..." };
4341
+ }
4342
+ if (TERMINATION_SIGNAL) {
4343
+ yield { type: "status", content: "Termination Signal Received." };
4344
+ await new Promise((resolve) => setTimeout(resolve, 1500));
4345
+ break;
4346
+ }
4347
+ if (steeringCallback) {
4348
+ const hint = await steeringCallback();
4349
+ if (hint) {
4350
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
4351
+ modifiedHistory[modifiedHistory.length - 1].text += `
4177
4352
 
4178
4353
  [STEERING HINT]: ${hint}`;
4179
- } else {
4180
- modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**\n" : ""}[STEERING HINT]: ${hint}` });
4354
+ } else {
4355
+ modifiedHistory.push({ role: "user", text: `${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**\n" : ""}[STEERING HINT]: ${hint}` });
4356
+ }
4357
+ yield { type: "status", content: "Steering Hint Injected." };
4181
4358
  }
4182
- yield { type: "status", content: "Steering Hint Injected." };
4183
4359
  }
4184
- }
4185
- let stream;
4186
- let success = false;
4187
- let retryCount = 1;
4188
- let inStreamRetryCount = 1;
4189
- let turnText = "";
4190
- let lastToolSniffed = null;
4191
- let lastToolDetail = null;
4192
- let lastToolEventTime = null;
4193
- let lastToolFinishedAt = 0;
4194
- let toolResults = [];
4195
- let toolCallPointer = 0;
4196
- let anyToolExecutedInThisTurn = false;
4197
- let isThinkingLoop = false;
4198
- let isStutteringLoop = false;
4199
- let isGeneralLoop = false;
4200
- let isInitialAttempt = true;
4201
- let accumulatedContext = "";
4202
- let dedupeBuffer = "";
4203
- let isDedupeActive = false;
4204
- while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
4205
- try {
4206
- turnText = "";
4207
- if (isInitialAttempt) {
4208
- if (process.stdout.isTTY) {
4209
- process.stdout.write(`\x1B]0;Working...\x07`);
4360
+ let stream;
4361
+ let success = false;
4362
+ let retryCount = 1;
4363
+ let inStreamRetryCount = 1;
4364
+ let turnText = "";
4365
+ let lastToolSniffed = null;
4366
+ let lastToolDetail = null;
4367
+ let lastToolEventTime = null;
4368
+ let lastToolFinishedAt = 0;
4369
+ let toolResults = [];
4370
+ let toolCallPointer = 0;
4371
+ let anyToolExecutedInThisTurn = false;
4372
+ let isThinkingLoop = false;
4373
+ let isStutteringLoop = false;
4374
+ let isGeneralLoop = false;
4375
+ let isInitialAttempt = true;
4376
+ let accumulatedContext = "";
4377
+ let dedupeBuffer = "";
4378
+ let isDedupeActive = false;
4379
+ while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
4380
+ try {
4381
+ turnText = "";
4382
+ if (isInitialAttempt) {
4383
+ if (process.stdout.isTTY) {
4384
+ process.stdout.write(`\x1B]0;Working...\x07`);
4385
+ }
4386
+ yield { type: "turn_reset", content: true };
4387
+ yield { type: "spinner", content: true };
4388
+ isInitialAttempt = false;
4389
+ if (inStreamRetryCount === 1) {
4390
+ accumulatedContext = "";
4391
+ }
4210
4392
  }
4211
- yield { type: "turn_reset", content: true };
4212
- yield { type: "spinner", content: true };
4213
- isInitialAttempt = false;
4214
- if (inStreamRetryCount === 1) {
4215
- accumulatedContext = "";
4393
+ const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
4394
+ const parts = [{ text: msg.text }];
4395
+ if (msg.binaryPart) {
4396
+ parts.push(msg.binaryPart);
4397
+ }
4398
+ return {
4399
+ role: msg.role === "user" || msg.role === "system" ? "user" : "model",
4400
+ parts
4401
+ };
4402
+ });
4403
+ if (!await checkQuota("agent", settings)) {
4404
+ throw new Error("Error: Daily Quota Exausted for Agent");
4216
4405
  }
4217
- }
4218
- const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
4219
- const parts = [{ text: msg.text }];
4220
- if (msg.binaryPart) {
4221
- parts.push(msg.binaryPart);
4406
+ let targetModel = modelName;
4407
+ if (retryCount === MAX_RETRIES - 1) {
4408
+ targetModel = "gemini-3-flash-preview";
4409
+ yield { type: "model_update", content: "Trying with fallback model" };
4410
+ } else if (retryCount === MAX_RETRIES) {
4411
+ targetModel = "gemini-3.5-flash";
4412
+ yield { type: "model_update", content: "Trying with fallback model" };
4413
+ } else if (retryCount > 12 && retryCount < MAX_RETRIES - 2 && settings.apiKey !== "custom") {
4414
+ targetModel = "gemma-4-31b-it";
4415
+ yield { type: "model_update", content: "Trying with fallback Gemma Model" };
4416
+ } else if (retryCount > 0) {
4417
+ yield { type: "model_update", content: null };
4222
4418
  }
4223
- return {
4224
- role: msg.role === "user" || msg.role === "system" ? "user" : "model",
4225
- parts
4226
- };
4227
- });
4228
- if (!await checkQuota("agent", settings)) {
4229
- throw new Error("Error: Daily Quota Exausted for Agent");
4230
- }
4231
- let targetModel = modelName;
4232
- if (retryCount === MAX_RETRIES - 1) {
4233
- targetModel = "gemini-3-flash-preview";
4234
- yield { type: "model_update", content: "Trying with fallback model" };
4235
- } else if (retryCount === MAX_RETRIES) {
4236
- targetModel = "gemini-3.5-flash";
4237
- yield { type: "model_update", content: "Trying with fallback model" };
4238
- } else if (retryCount > 12 && retryCount < MAX_RETRIES - 2 && settings.apiKey !== "custom") {
4239
- targetModel = "gemma-4-31b-it";
4240
- yield { type: "model_update", content: "Trying with fallback Gemma Model" };
4241
- } else if (retryCount > 0) {
4242
- yield { type: "model_update", content: null };
4243
- }
4244
- const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
4245
- const jitInstruction = `
4419
+ const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
4420
+ const jitInstruction = `
4246
4421
 
4247
4422
  [SYSTEM] Tool result received. Analyze output and proceed with your turn.${thinkingLevel != "Fast" ? "**STRICTLY MAINTAIN THINKING PROTOCOL. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}`;
4248
- const lastUserMsg = contents[contents.length - 1];
4249
- let addedMarker = false;
4250
- if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
4251
- lastUserMsg.parts[0].text += jitInstruction;
4252
- addedMarker = true;
4253
- }
4254
- const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.95 : 0.7));
4255
- const currentStep = loop + 1;
4256
- if (currentStep >= stepThreshold && lastUserMsg && lastUserMsg.parts?.[0]) {
4257
- lastUserMsg.parts[0].text += `
4423
+ const lastUserMsg = contents[contents.length - 1];
4424
+ let addedMarker = false;
4425
+ if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
4426
+ lastUserMsg.parts[0].text += jitInstruction;
4427
+ addedMarker = true;
4428
+ }
4429
+ const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.95 : 0.7));
4430
+ const currentStep = loop + 1;
4431
+ if (currentStep >= stepThreshold && lastUserMsg && lastUserMsg.parts?.[0]) {
4432
+ lastUserMsg.parts[0].text += `
4258
4433
  [SYSTEM] WARNING, Turn Limit Impending: Step ${currentStep}/${MAX_LOOPS}. Wrap up quickly/prompt user to continue & use [turn:finish] quickly.`;
4259
- }
4260
- stream = await client.models.generateContentStream({
4261
- model: targetModel || "gemma-4-31b-it",
4262
- contents,
4263
- config: {
4264
- systemInstruction: currentSystemInstruction,
4265
- temperature: mode === "Flux" ? 1 : 1.4,
4266
- maxOutputTokens: 32768,
4267
- mediaResolution: "MEDIA_RESOLUTION_MEDIUM",
4268
- safetySettings: [
4269
- { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
4270
- { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
4271
- { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
4272
- { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
4273
- ],
4274
- thinkingConfig: { includeThoughts: false, thinkingLevel: targetModel.includes("pro") ? ThinkingLevel.HIGH : ThinkingLevel.MINIMAL }
4275
4434
  }
4276
- });
4277
- if (addedMarker && contents[contents.length - 1]?.parts?.[0]) {
4278
- contents[contents.length - 1].parts[0].text = contents[contents.length - 1].parts[0].text.replace(jitInstruction, "").trim();
4279
- }
4280
- turnText = "";
4281
- lastToolSniffed = null;
4282
- lastToolEventTime = null;
4283
- toolResults = [];
4284
- toolCallPointer = 0;
4285
- yield { type: "model_update", content: null };
4286
- yield { type: "status", content: "Working..." };
4287
- dedupeBuffer = "";
4288
- isDedupeActive = accumulatedContext.length > 0;
4289
- for await (const chunk of stream) {
4290
- if (TERMINATION_SIGNAL) {
4291
- yield { type: "status", content: "Termination Signal Received." };
4292
- await new Promise((resolve) => setTimeout(resolve, 3e3));
4293
- break;
4435
+ stream = await client.models.generateContentStream({
4436
+ model: targetModel || "gemma-4-31b-it",
4437
+ contents,
4438
+ config: {
4439
+ systemInstruction: currentSystemInstruction,
4440
+ temperature: mode === "Flux" ? 1 : 1.4,
4441
+ maxOutputTokens: 32768,
4442
+ mediaResolution: "MEDIA_RESOLUTION_MEDIUM",
4443
+ safetySettings: [
4444
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
4445
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
4446
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
4447
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
4448
+ ],
4449
+ thinkingConfig: { includeThoughts: false, thinkingLevel: targetModel.includes("pro") ? ThinkingLevel.HIGH : ThinkingLevel.MINIMAL }
4450
+ }
4451
+ });
4452
+ if (addedMarker && contents[contents.length - 1]?.parts?.[0]) {
4453
+ contents[contents.length - 1].parts[0].text = contents[contents.length - 1].parts[0].text.replace(jitInstruction, "").trim();
4294
4454
  }
4295
- if (chunk.text) {
4296
- if (isDedupeActive) {
4297
- dedupeBuffer += chunk.text;
4298
- if (dedupeBuffer.length >= 30) {
4299
- let overlapLen = 0;
4300
- const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4301
- for (let len = maxPossibleOverlap; len > 0; len--) {
4302
- if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4303
- overlapLen = len;
4304
- break;
4455
+ turnText = "";
4456
+ lastToolSniffed = null;
4457
+ lastToolEventTime = null;
4458
+ toolResults = [];
4459
+ toolCallPointer = 0;
4460
+ yield { type: "model_update", content: null };
4461
+ yield { type: "status", content: "Working..." };
4462
+ dedupeBuffer = "";
4463
+ isDedupeActive = accumulatedContext.length > 0;
4464
+ for await (const chunk of stream) {
4465
+ if (TERMINATION_SIGNAL) {
4466
+ yield { type: "status", content: "Termination Signal Received." };
4467
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4468
+ break;
4469
+ }
4470
+ if (chunk.text) {
4471
+ if (isDedupeActive) {
4472
+ dedupeBuffer += chunk.text;
4473
+ if (dedupeBuffer.length >= 30) {
4474
+ let overlapLen = 0;
4475
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4476
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4477
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4478
+ overlapLen = len;
4479
+ break;
4480
+ }
4305
4481
  }
4306
- }
4307
- const cleanText = dedupeBuffer.substring(overlapLen);
4308
- if (cleanText) {
4309
- const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4310
- const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4311
- if (dedupeClean) {
4312
- turnText += dedupeClean;
4313
- yield { type: "text", content: dedupeClean };
4482
+ const cleanText = dedupeBuffer.substring(overlapLen);
4483
+ if (cleanText) {
4484
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4485
+ const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4486
+ if (dedupeClean) {
4487
+ turnText += dedupeClean;
4488
+ yield { type: "text", content: dedupeClean };
4489
+ }
4314
4490
  }
4491
+ isDedupeActive = false;
4492
+ dedupeBuffer = "";
4315
4493
  }
4316
- isDedupeActive = false;
4317
- dedupeBuffer = "";
4494
+ continue;
4495
+ } else {
4496
+ turnText += chunk.text;
4497
+ yield { type: "text", content: chunk.text };
4318
4498
  }
4319
- continue;
4320
- } else {
4321
- turnText += chunk.text;
4322
- yield { type: "text", content: chunk.text };
4323
- }
4324
- const signalSafeText3 = getSanitizedText(turnText);
4325
- const toolContext = getActiveToolContext(turnText);
4326
- if (toolContext.inside) {
4327
- if (!lastToolEventTime) lastToolEventTime = Date.now();
4328
- const rawToolName = toolContext.toolName;
4329
- const NORMALIZE_MAP = {
4330
- "Ask": "ask",
4331
- "WebSearch": "web_search",
4332
- "WebScrape": "web_scrape",
4333
- "ReadFile": "view_file",
4334
- "ReadFolder": "read_folder",
4335
- "WriteFile": "write_file",
4336
- "PatchFile": "update_file",
4337
- "WritePDF": "write_pdf",
4338
- "WriteDoc": "write_docx",
4339
- "Run": "exec_command",
4340
- "SearchKeyword": "search_keyword",
4341
- "Memory": "memory",
4342
- "Chat": "chat",
4343
- "chat": "chat",
4344
- "GenerateImage": "generate_image",
4345
- "generate_image": "generate_image"
4346
- };
4347
- const potentialTool = NORMALIZE_MAP[rawToolName] || rawToolName;
4348
- const partialArgs = toolContext.args || "";
4349
- let detail = null;
4350
- if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image"].includes(potentialTool)) {
4351
- const pArgs = parseArgs(partialArgs);
4352
- const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
4353
- const keyword = pArgs.keyword;
4354
- if (keyword) {
4355
- detail = keyword.replace(/["']/g, "");
4356
- } else if (filePath) {
4357
- detail = path14.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
4358
- } else {
4359
- const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
4360
- if (m) {
4361
- const val = m[1].replace(/["']/g, "");
4362
- detail = potentialTool === "search_keyword" ? val : path14.basename(val.replace(/\\/g, "/"));
4499
+ const signalSafeText3 = getSanitizedText(turnText);
4500
+ const toolContext = getActiveToolContext(turnText);
4501
+ if (toolContext.inside) {
4502
+ if (!lastToolEventTime) lastToolEventTime = Date.now();
4503
+ const rawToolName = toolContext.toolName;
4504
+ const NORMALIZE_MAP = {
4505
+ "Ask": "ask",
4506
+ "WebSearch": "web_search",
4507
+ "WebScrape": "web_scrape",
4508
+ "ReadFile": "view_file",
4509
+ "ReadFolder": "read_folder",
4510
+ "WriteFile": "write_file",
4511
+ "PatchFile": "update_file",
4512
+ "WritePDF": "write_pdf",
4513
+ "WriteDoc": "write_docx",
4514
+ "Run": "exec_command",
4515
+ "SearchKeyword": "search_keyword",
4516
+ "Memory": "memory",
4517
+ "Chat": "chat",
4518
+ "chat": "chat",
4519
+ "GenerateImage": "generate_image",
4520
+ "generate_image": "generate_image"
4521
+ };
4522
+ const potentialTool = NORMALIZE_MAP[rawToolName] || rawToolName;
4523
+ const partialArgs = toolContext.args || "";
4524
+ let detail = null;
4525
+ if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image"].includes(potentialTool)) {
4526
+ const pArgs = parseArgs(partialArgs);
4527
+ const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
4528
+ const keyword = pArgs.keyword;
4529
+ if (keyword) {
4530
+ detail = keyword.replace(/["']/g, "");
4531
+ } else if (filePath) {
4532
+ detail = path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
4533
+ } else {
4534
+ const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
4535
+ if (m) {
4536
+ const val = m[1].replace(/["']/g, "");
4537
+ detail = potentialTool === "search_keyword" ? val : path15.basename(val.replace(/\\/g, "/"));
4538
+ }
4363
4539
  }
4364
4540
  }
4365
- }
4366
- const currentLabel = `${TOOL_LABELS2[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
4367
- if (potentialTool !== lastToolSniffed || detail !== lastToolDetail) {
4368
- lastToolSniffed = potentialTool;
4369
- lastToolDetail = detail;
4370
- yield { type: "status", content: `${currentLabel}...` };
4371
- if (process.stdout.isTTY) {
4372
- const TOOL_TITLES = {
4373
- "web_search": "Searching Web",
4374
- "web_scrape": "Reading Website",
4375
- "view_file": "Reading File",
4376
- "read_folder": "Listing Folder",
4377
- "list_files": "Listing Folder",
4378
- "write_file": "Writing File",
4379
- "update_file": "Updating File",
4380
- "write_pdf": "Creating PDF",
4381
- "write_docx": "Creating Word Doc",
4382
- "search_keyword": "Searching Keywords",
4383
- "exec_command": "Running Command",
4384
- "ask": "Asking User",
4385
- "memory": "Updating Memory",
4386
- "generate_image": "Generating Image"
4387
- };
4388
- const toolTitle = TOOL_TITLES[potentialTool] || "Working";
4389
- process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
4390
- }
4391
- }
4392
- }
4393
- const contextSafeText = getContextSafeText(turnText, false);
4394
- const thinkBlocks = contextSafeText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
4395
- const thinkContent = thinkBlocks.join("").trim();
4396
- const sentences = thinkContent.split(/[.!?]\s+/);
4397
- const uniqueSentences = new Set(sentences);
4398
- const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
4399
- const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
4400
- let repetitionThresholdThinking = 0.4;
4401
- let repetitionThresholdResponse = 0.6;
4402
- const thinkingCaps = {
4403
- "low": 200,
4404
- "medium": 500,
4405
- "high": 2e3,
4406
- "max": 3500,
4407
- "xhigh": 3500
4408
- };
4409
- const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
4410
- let isOverVerboseThinking = wordCount > cap;
4411
- if (repetitionRatio > repetitionThresholdThinking || isOverVerboseThinking) {
4412
- const reason = repetitionRatio > repetitionThresholdThinking ? "Thinking Loop Detected" : "Thinking Budget Exceeded";
4413
- yield { type: "status", content: `${reason}. Re-centering...` };
4414
- isThinkingLoop = true;
4415
- await new Promise((resolve) => setTimeout(resolve, 3e3));
4416
- break;
4417
- }
4418
- const responseContent = signalSafeText3.trim();
4419
- const respSentences = responseContent.split(/[.!?]\s+/);
4420
- const uniqueRespSentences = new Set(respSentences);
4421
- const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
4422
- if (respRepetitionRatio > repetitionThresholdResponse) {
4423
- yield { type: "status", content: `Response Loop Detected. Re-centering...` };
4424
- isThinkingLoop = false;
4425
- isGeneralLoop = true;
4426
- await new Promise((resolve) => setTimeout(resolve, 3e3));
4427
- break;
4428
- }
4429
- const allWords = contextSafeText.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
4430
- let stutterDetected = false;
4431
- if (allWords.length > 5) {
4432
- for (let p = 1; p <= 15; p++) {
4433
- const R = Math.max(3, Math.ceil(8 / p));
4434
- if (allWords.length < p * R) continue;
4435
- let isRepeating = true;
4436
- const pattern = allWords.slice(allWords.length - p);
4437
- const patternStr = pattern.join(" ");
4438
- for (let r = 1; r < R; r++) {
4439
- const prevPattern = allWords.slice(allWords.length - p * (r + 1), allWords.length - p * r);
4440
- if (prevPattern.join(" ") !== patternStr) {
4441
- isRepeating = false;
4442
- break;
4541
+ const currentLabel = `${TOOL_LABELS2[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
4542
+ if (potentialTool !== lastToolSniffed || detail !== lastToolDetail) {
4543
+ lastToolSniffed = potentialTool;
4544
+ lastToolDetail = detail;
4545
+ yield { type: "status", content: `${currentLabel}...` };
4546
+ if (process.stdout.isTTY) {
4547
+ const TOOL_TITLES = {
4548
+ "web_search": "Searching Web",
4549
+ "web_scrape": "Reading Website",
4550
+ "view_file": "Reading File",
4551
+ "read_folder": "Listing Folder",
4552
+ "list_files": "Listing Folder",
4553
+ "write_file": "Writing File",
4554
+ "update_file": "Updating File",
4555
+ "write_pdf": "Creating PDF",
4556
+ "write_docx": "Creating Word Doc",
4557
+ "search_keyword": "Searching Keywords",
4558
+ "exec_command": "Running Command",
4559
+ "ask": "Asking User",
4560
+ "memory": "Updating Memory",
4561
+ "generate_image": "Generating Image"
4562
+ };
4563
+ const toolTitle = TOOL_TITLES[potentialTool] || "Working";
4564
+ process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
4443
4565
  }
4444
4566
  }
4445
- if (isRepeating) {
4446
- stutterDetected = true;
4447
- break;
4448
- }
4449
4567
  }
4450
- }
4451
- if (!stutterDetected) {
4452
- const cleanChars = contextSafeText.toLowerCase().replace(/[^a-z0-9]/gi, "");
4453
- if (cleanChars.length >= 10) {
4454
- for (let p = 1; p <= 10; p++) {
4455
- const R = Math.max(4, Math.ceil(12 / p));
4456
- if (cleanChars.length < p * R) continue;
4457
- const pattern = cleanChars.substring(cleanChars.length - p);
4568
+ const contextSafeText = getContextSafeText(turnText, false);
4569
+ const thinkBlocks = contextSafeText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
4570
+ const thinkContent = thinkBlocks.join("").trim();
4571
+ const sentences = thinkContent.split(/[.!?]\s+/);
4572
+ const uniqueSentences = new Set(sentences);
4573
+ const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
4574
+ const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
4575
+ let repetitionThresholdThinking = 0.4;
4576
+ let repetitionThresholdResponse = 0.6;
4577
+ const thinkingCaps = {
4578
+ "low": 200,
4579
+ "medium": 500,
4580
+ "high": 2e3,
4581
+ "max": 3500,
4582
+ "xhigh": 3500
4583
+ };
4584
+ const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
4585
+ let isOverVerboseThinking = wordCount > cap;
4586
+ if (repetitionRatio > repetitionThresholdThinking || isOverVerboseThinking) {
4587
+ const reason = repetitionRatio > repetitionThresholdThinking ? "Thinking Loop Detected" : "Thinking Budget Exceeded";
4588
+ yield { type: "status", content: `${reason}. Re-centering...` };
4589
+ isThinkingLoop = true;
4590
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4591
+ break;
4592
+ }
4593
+ const responseContent = signalSafeText3.trim();
4594
+ const respSentences = responseContent.split(/[.!?]\s+/);
4595
+ const uniqueRespSentences = new Set(respSentences);
4596
+ const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
4597
+ if (respRepetitionRatio > repetitionThresholdResponse) {
4598
+ yield { type: "status", content: `Response Loop Detected. Re-centering...` };
4599
+ isThinkingLoop = false;
4600
+ isGeneralLoop = true;
4601
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4602
+ break;
4603
+ }
4604
+ const allWords = contextSafeText.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
4605
+ let stutterDetected = false;
4606
+ if (allWords.length > 5) {
4607
+ for (let p = 1; p <= 15; p++) {
4608
+ const R = Math.max(3, Math.ceil(8 / p));
4609
+ if (allWords.length < p * R) continue;
4458
4610
  let isRepeating = true;
4611
+ const pattern = allWords.slice(allWords.length - p);
4612
+ const patternStr = pattern.join(" ");
4459
4613
  for (let r = 1; r < R; r++) {
4460
- const prevPattern = cleanChars.substring(cleanChars.length - p * (r + 1), cleanChars.length - p * r);
4461
- if (prevPattern !== pattern) {
4614
+ const prevPattern = allWords.slice(allWords.length - p * (r + 1), allWords.length - p * r);
4615
+ if (prevPattern.join(" ") !== patternStr) {
4462
4616
  isRepeating = false;
4463
4617
  break;
4464
4618
  }
@@ -4469,400 +4623,424 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CORE
4469
4623
  }
4470
4624
  }
4471
4625
  }
4472
- }
4473
- if (stutterDetected) {
4474
- yield { type: "status", content: `Stuttering Detected. Re-centering...` };
4475
- isThinkingLoop = false;
4476
- isStutteringLoop = true;
4477
- await new Promise((resolve) => setTimeout(resolve, 3e3));
4478
- break;
4479
- }
4480
- const toolActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
4481
- const allToolsFound = detectToolCalls(toolActionableText);
4482
- while (allToolsFound.length > toolCallPointer) {
4483
- const toolCall = allToolsFound[toolCallPointer];
4484
- const NORMALIZE_MAP = {
4485
- "Ask": "ask",
4486
- "WebSearch": "web_search",
4487
- "WebScrape": "web_scrape",
4488
- "ReadFile": "view_file",
4489
- "ReadFolder": "read_folder",
4490
- "WriteFile": "write_file",
4491
- "PatchFile": "update_file",
4492
- "WritePDF": "write_pdf",
4493
- "WriteDoc": "write_docx",
4494
- "Run": "exec_command",
4495
- "SearchKeyword": "search_keyword",
4496
- "Memory": "memory",
4497
- "Chat": "chat",
4498
- "chat": "chat",
4499
- "GenerateImage": "generate_image",
4500
- "generate_image": "generate_image"
4501
- };
4502
- const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
4503
- const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
4504
- const detail = getToolDetail(normToolName, toolCall.args);
4505
- yield { type: "status", content: `${displayLabel}${detail ? ` (${detail})` : ""}...` };
4506
- let label = "";
4507
- if (normToolName === "web_search") {
4508
- const { query, limit = 10 } = parseArgs(toolCall.args);
4509
- label = `\u{1F50D} SEARCHED: "${query}" (${limit})`.toUpperCase();
4510
- } else if (normToolName === "web_scrape") {
4511
- const url = parseArgs(toolCall.args).url || "...";
4512
- label = `\u{1F4D6} READ SITE: ${url}`.toUpperCase();
4513
- } else if (normToolName === "view_file") {
4514
- const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
4515
- const rawStart = StartLine || start_line;
4516
- const rawEnd = EndLine || end_line;
4517
- const sLine = parseInt(rawStart) || 1;
4518
- const eLine = parseInt(rawEnd) || (rawStart ? sLine + 800 : 800);
4519
- let totalLines = "...";
4520
- let actualEndLine = eLine;
4521
- try {
4522
- const absPath = path14.resolve(process.cwd(), targetPath2);
4523
- if (fs15.existsSync(absPath)) {
4524
- const content = fs15.readFileSync(absPath, "utf8");
4525
- const lines = content.split("\n").length;
4526
- totalLines = lines;
4527
- actualEndLine = Math.min(eLine, lines);
4626
+ if (!stutterDetected) {
4627
+ const cleanChars = contextSafeText.toLowerCase().replace(/[^a-z0-9]/gi, "");
4628
+ if (cleanChars.length >= 10) {
4629
+ for (let p = 1; p <= 10; p++) {
4630
+ const R = Math.max(4, Math.ceil(12 / p));
4631
+ if (cleanChars.length < p * R) continue;
4632
+ const pattern = cleanChars.substring(cleanChars.length - p);
4633
+ let isRepeating = true;
4634
+ for (let r = 1; r < R; r++) {
4635
+ const prevPattern = cleanChars.substring(cleanChars.length - p * (r + 1), cleanChars.length - p * r);
4636
+ if (prevPattern !== pattern) {
4637
+ isRepeating = false;
4638
+ break;
4639
+ }
4640
+ }
4641
+ if (isRepeating) {
4642
+ stutterDetected = true;
4643
+ break;
4644
+ }
4528
4645
  }
4529
- } catch (e) {
4530
4646
  }
4531
- const pathLower = targetPath2.toLowerCase();
4532
- const isPdf = pathLower.endsWith(".pdf");
4533
- const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
4534
- if (isPdf) {
4535
- label = `\u{1F4C4} ANALYZED PDF: ${targetPath2}`.toUpperCase();
4536
- } else if (isImage) {
4537
- label = `\u{1F4F8} ANALYZED IMAGE: ${targetPath2}`.toUpperCase();
4647
+ }
4648
+ if (stutterDetected) {
4649
+ yield { type: "status", content: `Stuttering Detected. Re-centering...` };
4650
+ isThinkingLoop = false;
4651
+ isStutteringLoop = true;
4652
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4653
+ break;
4654
+ }
4655
+ const toolActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
4656
+ const allToolsFound = detectToolCalls(toolActionableText);
4657
+ while (allToolsFound.length > toolCallPointer) {
4658
+ const toolCall = allToolsFound[toolCallPointer];
4659
+ const NORMALIZE_MAP = {
4660
+ "Ask": "ask",
4661
+ "WebSearch": "web_search",
4662
+ "WebScrape": "web_scrape",
4663
+ "ReadFile": "view_file",
4664
+ "ReadFolder": "read_folder",
4665
+ "WriteFile": "write_file",
4666
+ "PatchFile": "update_file",
4667
+ "WritePDF": "write_pdf",
4668
+ "WriteDoc": "write_docx",
4669
+ "Run": "exec_command",
4670
+ "SearchKeyword": "search_keyword",
4671
+ "Memory": "memory",
4672
+ "Chat": "chat",
4673
+ "chat": "chat",
4674
+ "GenerateImage": "generate_image",
4675
+ "generate_image": "generate_image"
4676
+ };
4677
+ const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
4678
+ const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
4679
+ const detail = getToolDetail(normToolName, toolCall.args);
4680
+ yield { type: "status", content: `${displayLabel}${detail ? ` (${detail})` : ""}...` };
4681
+ let label = "";
4682
+ if (normToolName === "web_search") {
4683
+ const { query, limit = 10 } = parseArgs(toolCall.args);
4684
+ label = `\u{1F50D} SEARCHED: "${query}" (${limit})`.toUpperCase();
4685
+ } else if (normToolName === "web_scrape") {
4686
+ const url = parseArgs(toolCall.args).url || "...";
4687
+ label = `\u{1F4D6} READ SITE: ${url}`.toUpperCase();
4688
+ } else if (normToolName === "view_file") {
4689
+ const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
4690
+ const rawStart = StartLine || start_line;
4691
+ const rawEnd = EndLine || end_line;
4692
+ const sLine = parseInt(rawStart) || 1;
4693
+ const eLine = parseInt(rawEnd) || (rawStart ? sLine + 800 : 800);
4694
+ let totalLines = "...";
4695
+ let actualEndLine = eLine;
4696
+ try {
4697
+ const absPath = path15.resolve(process.cwd(), targetPath2);
4698
+ if (fs16.existsSync(absPath)) {
4699
+ const content = fs16.readFileSync(absPath, "utf8");
4700
+ const lines = content.split("\n").length;
4701
+ totalLines = lines;
4702
+ actualEndLine = Math.min(eLine, lines);
4703
+ }
4704
+ } catch (e) {
4705
+ }
4706
+ const pathLower = targetPath2.toLowerCase();
4707
+ const isPdf = pathLower.endsWith(".pdf");
4708
+ const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
4709
+ if (isPdf) {
4710
+ label = `\u{1F4C4} ANALYZED PDF: ${targetPath2}`.toUpperCase();
4711
+ } else if (isImage) {
4712
+ label = `\u{1F4F8} ANALYZED IMAGE: ${targetPath2}`.toUpperCase();
4713
+ } else {
4714
+ label = `\u{1F4C4} ANALYZED FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
4715
+ }
4716
+ } else if (normToolName === "list_files" || normToolName === "read_folder") {
4717
+ const action = normToolName === "list_files" ? "LIST" : "ANALYSED";
4718
+ label = `\u{1F4C2} ${action} FOLDER: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
4719
+ } else if (normToolName === "write_file" || normToolName === "update_file") {
4720
+ const action = normToolName === "write_file" ? "WRITTEN" : "UPDATED FILE";
4721
+ label = `\u{1F4BE} ${action}: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4722
+ } else if (normToolName === "write_pdf") {
4723
+ label = `\u{1F4D1} PDF CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4724
+ } else if (normToolName === "write_docx") {
4725
+ label = `\u{1F4DD} DOCX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4726
+ } else if (normToolName === "search_keyword") {
4727
+ const { keyword } = parseArgs(toolCall.args);
4728
+ label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
4729
+ } else if (normToolName === "generate_image") {
4730
+ const { path: argPath, outputPath, output } = parseArgs(toolCall.args);
4731
+ label = `\u{1F3A8} IMAGE GENERATED: ${argPath || outputPath || output || "generated_image.png"}`.toUpperCase();
4732
+ } else if (normToolName === "exec_command" || normToolName === "ask") {
4733
+ label = "";
4538
4734
  } else {
4539
- label = `\u{1F4C4} ANALYZED FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
4735
+ label = `EXECUTED: ${toolCall.toolName}`.toUpperCase();
4540
4736
  }
4541
- } else if (normToolName === "list_files" || normToolName === "read_folder") {
4542
- const action = normToolName === "list_files" ? "LIST" : "ANALYSED";
4543
- label = `\u{1F4C2} ${action} FOLDER: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
4544
- } else if (normToolName === "write_file" || normToolName === "update_file") {
4545
- const action = normToolName === "write_file" ? "WRITTEN" : "UPDATED FILE";
4546
- label = `\u{1F4BE} ${action}: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4547
- } else if (normToolName === "write_pdf") {
4548
- label = `\u{1F4D1} PDF CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4549
- } else if (normToolName === "write_docx") {
4550
- label = `\u{1F4DD} DOCX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4551
- } else if (normToolName === "search_keyword") {
4552
- const { keyword } = parseArgs(toolCall.args);
4553
- label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
4554
- } else if (normToolName === "generate_image") {
4555
- const { path: argPath, outputPath, output } = parseArgs(toolCall.args);
4556
- label = `\u{1F3A8} IMAGE GENERATED: ${argPath || outputPath || output || "generated_image.png"}`.toUpperCase();
4557
- } else if (normToolName === "exec_command" || normToolName === "ask") {
4558
- label = "";
4559
- } else {
4560
- label = `EXECUTED: ${toolCall.toolName}`.toUpperCase();
4561
- }
4562
- if (label) {
4563
- const boxWidth = Math.min(label.length + 4, 115);
4564
- const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
4565
- const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
4566
- const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
4567
- yield { type: "visual_feedback", content: `${boxTop}
4737
+ if (label) {
4738
+ const boxWidth = Math.min(label.length + 4, 115);
4739
+ const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
4740
+ const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
4741
+ const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
4742
+ yield { type: "visual_feedback", content: `${boxTop}
4568
4743
  ${boxMid}
4569
4744
  ${boxBottom}` };
4570
- }
4571
- if (normToolName === "exec_command") {
4572
- const { command } = parseArgs(toolCall.args);
4573
- if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
4574
- const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
4575
- const currentDrive = path14.resolve(process.cwd()).substring(0, 3).toLowerCase();
4576
- const isViolating = riskyPatterns.some((pattern) => {
4577
- if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
4578
- const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
4579
- return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
4745
+ }
4746
+ if (normToolName === "exec_command") {
4747
+ const { command } = parseArgs(toolCall.args);
4748
+ if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
4749
+ const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
4750
+ const currentDrive = path15.resolve(process.cwd()).substring(0, 3).toLowerCase();
4751
+ const isViolating = riskyPatterns.some((pattern) => {
4752
+ if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
4753
+ const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
4754
+ return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
4755
+ }
4756
+ return pattern.test(command);
4757
+ });
4758
+ if (isViolating) {
4759
+ const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
4760
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}` });
4761
+ yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
4762
+ toolCallPointer++;
4763
+ continue;
4580
4764
  }
4581
- return pattern.test(command);
4582
- });
4583
- if (isViolating) {
4584
- const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
4585
- toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}` });
4765
+ }
4766
+ if (settings.onExecStart) settings.onExecStart(command || "Unknown");
4767
+ yield { type: "exec_start" };
4768
+ }
4769
+ const parsedArgs = parseArgs(toolCall.args);
4770
+ const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
4771
+ if (targetPath) {
4772
+ const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
4773
+ const absoluteTarget = path15.resolve(targetPath);
4774
+ const absoluteCwd = path15.resolve(process.cwd());
4775
+ if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
4776
+ const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
4777
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
4586
4778
  yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
4587
4779
  toolCallPointer++;
4588
4780
  continue;
4589
4781
  }
4590
4782
  }
4591
- if (settings.onExecStart) settings.onExecStart(command || "Unknown");
4592
- yield { type: "exec_start" };
4593
- }
4594
- const parsedArgs = parseArgs(toolCall.args);
4595
- const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
4596
- if (targetPath) {
4597
- const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
4598
- const absoluteTarget = path14.resolve(targetPath);
4599
- const absoluteCwd = path14.resolve(process.cwd());
4600
- if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
4601
- const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace. To enable this, ask the user to turn on "External Workspace Access" in /settings.`;
4602
- toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
4603
- yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
4604
- toolCallPointer++;
4605
- continue;
4783
+ if (settings.onToolApproval) {
4784
+ let shouldPrompt = normToolName === "write_file" || normToolName === "update_file" || normToolName === "exec_command";
4785
+ if (shouldPrompt) {
4786
+ const approval = await settings.onToolApproval(normToolName, toolCall.args);
4787
+ if (approval === "deny") {
4788
+ if (normToolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
4789
+ const denyMsg = `Permission Denied: User rejected the ${normToolName === "exec_command" ? "terminal execution" : "file edit"}.`;
4790
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: DENIED: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
4791
+ yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
4792
+ await incrementUsage("toolDenied");
4793
+ if (settings.onToolResult) settings.onToolResult("denied", normToolName);
4794
+ toolCallPointer++;
4795
+ continue;
4796
+ }
4797
+ }
4606
4798
  }
4607
- }
4608
- if (settings.onToolApproval) {
4609
- let shouldPrompt = normToolName === "write_file" || normToolName === "update_file" || normToolName === "exec_command";
4610
- if (shouldPrompt) {
4611
- const approval = await settings.onToolApproval(normToolName, toolCall.args);
4612
- if (approval === "deny") {
4613
- if (normToolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
4614
- const denyMsg = `Permission Denied: User rejected the ${normToolName === "exec_command" ? "terminal execution" : "file edit"}.`;
4615
- toolResults.push({ role: "user", text: `[TOOL RESULT]: DENIED: ${denyMsg}${thinkingLevel != "Fast" ? "\n\n[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS STRICT PRIORITY. DO NOT START A RESPONSE WITHOUT THINKING**" : ""}` });
4616
- yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
4617
- await incrementUsage("toolDenied");
4618
- if (settings.onToolResult) settings.onToolResult("denied", normToolName);
4619
- toolCallPointer++;
4620
- continue;
4799
+ if (lastToolFinishedAt > 0) {
4800
+ const timeSinceLastTool = Date.now() - lastToolFinishedAt;
4801
+ if (timeSinceLastTool < 1e3) {
4802
+ await new Promise((resolve) => setTimeout(resolve, 1e3 - timeSinceLastTool));
4621
4803
  }
4622
4804
  }
4623
- }
4624
- if (lastToolFinishedAt > 0) {
4625
- const timeSinceLastTool = Date.now() - lastToolFinishedAt;
4626
- if (timeSinceLastTool < 1e3) {
4627
- await new Promise((resolve) => setTimeout(resolve, 1e3 - timeSinceLastTool));
4805
+ const effectiveStart = lastToolEventTime || Date.now();
4806
+ yield { type: "spinner", content: false };
4807
+ let result = await dispatchTool(normToolName, toolCall.args, {
4808
+ chatId,
4809
+ history,
4810
+ onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
4811
+ onAskUser: settings.onAskUser
4812
+ });
4813
+ yield { type: "spinner", content: true };
4814
+ if (process.stdout.isTTY) {
4815
+ process.stdout.write(`\x1B]0;Working...\x07`);
4628
4816
  }
4817
+ const toolEnd = Date.now();
4818
+ lastToolFinishedAt = toolEnd;
4819
+ yield { type: "tool_time", content: toolEnd - effectiveStart };
4820
+ lastToolEventTime = toolEnd;
4821
+ let binaryPart = null;
4822
+ if (typeof result === "object" && result.binaryPart) {
4823
+ binaryPart = result.binaryPart;
4824
+ result = result.text;
4825
+ }
4826
+ if (normToolName === "exec_command" && settings.onExecEnd) {
4827
+ await new Promise((resolve) => setTimeout(resolve, 800));
4828
+ settings.onExecEnd();
4829
+ }
4830
+ const isDenied = result && result.startsWith("DENIED:");
4831
+ const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
4832
+ if (isSuccess) {
4833
+ await incrementUsage("toolSuccess");
4834
+ if (settings.onToolResult) settings.onToolResult("success", normToolName);
4835
+ } else if (isDenied) {
4836
+ } else {
4837
+ await incrementUsage("toolFailure");
4838
+ if (settings.onToolResult) settings.onToolResult("failure", normToolName);
4839
+ }
4840
+ const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
4841
+ toolResults.push({ role: "user", text: aiContent, binaryPart });
4842
+ anyToolExecutedInThisTurn = true;
4843
+ let uiContent = `[TOOL RESULT]: ${result || ""}`;
4844
+ if (normToolName === "view_file" || normToolName === "web_scrape") {
4845
+ uiContent = `[TOOL RESULT]: ${label} (Context Locked for UI Clarity)`;
4846
+ }
4847
+ yield { type: "tool_result", content: uiContent, aiContent, binaryPart, toolName: normToolName };
4848
+ if (normToolName === "memory" && result.includes("SUCCESS")) yield { type: "memory_updated" };
4849
+ toolCallPointer++;
4629
4850
  }
4630
- const effectiveStart = lastToolEventTime || Date.now();
4631
- yield { type: "spinner", content: false };
4632
- let result = await dispatchTool(normToolName, toolCall.args, {
4633
- chatId,
4634
- history,
4635
- onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
4636
- onAskUser: settings.onAskUser
4637
- });
4638
- yield { type: "spinner", content: true };
4639
- if (process.stdout.isTTY) {
4640
- process.stdout.write(`\x1B]0;Working...\x07`);
4641
- }
4642
- const toolEnd = Date.now();
4643
- lastToolFinishedAt = toolEnd;
4644
- yield { type: "tool_time", content: toolEnd - effectiveStart };
4645
- lastToolEventTime = toolEnd;
4646
- let binaryPart = null;
4647
- if (typeof result === "object" && result.binaryPart) {
4648
- binaryPart = result.binaryPart;
4649
- result = result.text;
4650
- }
4651
- if (normToolName === "exec_command" && settings.onExecEnd) {
4652
- await new Promise((resolve) => setTimeout(resolve, 800));
4653
- settings.onExecEnd();
4654
- }
4655
- const isDenied = result && result.startsWith("DENIED:");
4656
- const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
4657
- if (isSuccess) {
4658
- await incrementUsage("toolSuccess");
4659
- if (settings.onToolResult) settings.onToolResult("success", normToolName);
4660
- } else if (isDenied) {
4661
- } else {
4662
- await incrementUsage("toolFailure");
4663
- if (settings.onToolResult) settings.onToolResult("failure", normToolName);
4664
- }
4665
- const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
4666
- toolResults.push({ role: "user", text: aiContent, binaryPart });
4667
- anyToolExecutedInThisTurn = true;
4668
- let uiContent = `[TOOL RESULT]: ${result || ""}`;
4669
- if (normToolName === "view_file" || normToolName === "web_scrape") {
4670
- uiContent = `[TOOL RESULT]: ${label} (Context Locked for UI Clarity)`;
4671
- }
4672
- yield { type: "tool_result", content: uiContent, aiContent, binaryPart, toolName: normToolName };
4673
- if (normToolName === "memory" && result.includes("SUCCESS")) yield { type: "memory_updated" };
4674
- toolCallPointer++;
4675
4851
  }
4676
- }
4677
- lastUsage = chunk.usageMetadata;
4678
- if (lastUsage) {
4679
- yield { type: "liveTokens", content: lastUsage.totalTokenCount };
4680
- }
4681
- }
4682
- if (isDedupeActive && dedupeBuffer.length > 0) {
4683
- let overlapLen = 0;
4684
- const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4685
- for (let len = maxPossibleOverlap; len > 0; len--) {
4686
- if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4687
- overlapLen = len;
4688
- break;
4852
+ lastUsage = chunk.usageMetadata;
4853
+ if (lastUsage) {
4854
+ yield { type: "liveTokens", content: lastUsage.totalTokenCount };
4689
4855
  }
4690
4856
  }
4691
- const cleanText = dedupeBuffer.substring(overlapLen);
4692
- if (cleanText) {
4693
- const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4694
- const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4695
- if (dedupeClean) {
4696
- turnText += dedupeClean;
4697
- yield { type: "text", content: dedupeClean };
4857
+ if (isDedupeActive && dedupeBuffer.length > 0) {
4858
+ let overlapLen = 0;
4859
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4860
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4861
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4862
+ overlapLen = len;
4863
+ break;
4864
+ }
4698
4865
  }
4866
+ const cleanText = dedupeBuffer.substring(overlapLen);
4867
+ if (cleanText) {
4868
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4869
+ const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4870
+ if (dedupeClean) {
4871
+ turnText += dedupeClean;
4872
+ yield { type: "text", content: dedupeClean };
4873
+ }
4874
+ }
4875
+ isDedupeActive = false;
4876
+ dedupeBuffer = "";
4877
+ }
4878
+ if (TERMINATION_SIGNAL) break;
4879
+ const signalSafeText2 = (turnText || "").trim();
4880
+ const hasFinish2 = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText2.toLowerCase());
4881
+ const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
4882
+ const didCallTool = toolResults.length > 0 || lastToolSniffed !== null;
4883
+ const pureOutputText = signalSafeText2.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
4884
+ const endsNormally = /[.!?}"'`’“”]$|```$/s.test(pureOutputText);
4885
+ if (!hasFinish2 && !hasContinue && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
4886
+ throw new Error("Silent stream cutoff (500): Model stream closed cleanly but cut off mid-sentence without signals.");
4699
4887
  }
4700
- isDedupeActive = false;
4701
- dedupeBuffer = "";
4702
- }
4703
- if (TERMINATION_SIGNAL) break;
4704
- const signalSafeText2 = (turnText || "").trim();
4705
- const hasFinish2 = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText2.toLowerCase());
4706
- const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
4707
- const didCallTool = toolResults.length > 0 || lastToolSniffed !== null;
4708
- const pureOutputText = signalSafeText2.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
4709
- const endsNormally = /[.!?}"'`’“”]$|```$/s.test(pureOutputText);
4710
- if (!hasFinish2 && !hasContinue && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
4711
- throw new Error("Silent stream cutoff (500): Model stream closed cleanly but cut off mid-sentence without signals.");
4712
- }
4713
- success = true;
4714
- await incrementUsage("agent");
4715
- } catch (err) {
4716
- if (String(err).includes("Incomplete JSON segment at the end")) {
4717
4888
  success = true;
4718
4889
  await incrementUsage("agent");
4719
- break;
4720
- }
4721
- if (isDedupeActive && dedupeBuffer.length > 0) {
4722
- let overlapLen = 0;
4723
- const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4724
- for (let len = maxPossibleOverlap; len > 0; len--) {
4725
- if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4726
- overlapLen = len;
4727
- break;
4728
- }
4890
+ } catch (err) {
4891
+ if (String(err).includes("Incomplete JSON segment at the end")) {
4892
+ success = true;
4893
+ await incrementUsage("agent");
4894
+ break;
4729
4895
  }
4730
- const cleanText = dedupeBuffer.substring(overlapLen);
4731
- if (cleanText) {
4732
- const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4733
- const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4734
- if (dedupeClean) {
4735
- turnText += dedupeClean;
4896
+ if (isDedupeActive && dedupeBuffer.length > 0) {
4897
+ let overlapLen = 0;
4898
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4899
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4900
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4901
+ overlapLen = len;
4902
+ break;
4903
+ }
4736
4904
  }
4905
+ const cleanText = dedupeBuffer.substring(overlapLen);
4906
+ if (cleanText) {
4907
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4908
+ const dedupeClean = hasOpenThink ? cleanText.replace(/^\s*<(think|thought)>\s*/gi, "") : cleanText.replace(/^\s*<(think|thought)>[\s\S]*?<\/(think|thought)>\s*/gi, "").replace(/^\s*<(think|thought)>\s*/gi, "");
4909
+ if (dedupeClean) {
4910
+ turnText += dedupeClean;
4911
+ }
4912
+ }
4913
+ isDedupeActive = false;
4914
+ dedupeBuffer = "";
4737
4915
  }
4738
- isDedupeActive = false;
4739
- dedupeBuffer = "";
4740
- }
4741
- const errMsg = err.status || err.error && err.error.message || String(err);
4742
- const errLog = String(err);
4743
- const date = (/* @__PURE__ */ new Date()).toLocaleString();
4744
- const agentErrDir = path14.join(LOGS_DIR, "agent");
4745
- if (!fs15.existsSync(agentErrDir)) fs15.mkdirSync(agentErrDir, { recursive: true });
4746
- fs15.appendFileSync(path14.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
4916
+ const errMsg = err.status || err.error && err.error.message || String(err);
4917
+ const errLog = String(err);
4918
+ const date = (/* @__PURE__ */ new Date()).toLocaleString();
4919
+ const agentErrDir = path15.join(LOGS_DIR, "agent");
4920
+ if (!fs16.existsSync(agentErrDir)) fs16.mkdirSync(agentErrDir, { recursive: true });
4921
+ fs16.appendFileSync(path15.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
4747
4922
 
4748
4923
  ----------------------------------------------------------------------
4749
4924
 
4750
4925
  `);
4751
- const status = err.status || err.statusCode || err.code;
4752
- const isRetryable = status && (status >= 500 && status < 600 || status === 408) || !status && (/status[ :]+(5\d\d|408)/i.test(String(err)) || /code[ :]+(5\d\d|408)/i.test(String(err)) || /(500|503|408)/.test(String(err)));
4753
- if (!isRetryable) {
4754
- if (retryCount < MAX_RETRIES - 3) {
4755
- throw err;
4926
+ const status = err.status || err.statusCode || err.code;
4927
+ const isRetryable = status && (status >= 500 && status < 600 || status === 408) || !status && (/status[ :]+(5\d\d|408)/i.test(String(err)) || /code[ :]+(5\d\d|408)/i.test(String(err)) || /(500|503|408)/.test(String(err)));
4928
+ if (!isRetryable) {
4929
+ if (retryCount < MAX_RETRIES - 3) {
4930
+ throw err;
4931
+ }
4756
4932
  }
4757
- }
4758
- if (turnText.trim().length > 0 || inStreamRetryCount > 1) {
4759
- if (inStreamRetryCount <= MAX_RETRIES) {
4760
- inStreamRetryCount++;
4761
- const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
4762
- if (turnText.trim().length > 0) {
4763
- modifiedHistory.push({ role: "agent", text: turnText });
4764
- const recoveryText = "[SYSTEM: STREAM RECOVERY]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption.\n- NO REPETITION: Do not repeat any text already written.\n- NO RE-THINK: Do not restart or open <think> if reasoning already started.\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start.\n- STEALTH: Do not mention/apologize for cutoff.\n- KEEP LENGTH: Maintain standard depth/length.";
4765
- if (toolResults.length > 0) {
4766
- toolResults.forEach((tr, idx) => {
4767
- if (idx === toolResults.length - 1) {
4768
- modifiedHistory.push({
4769
- ...tr,
4770
- text: `${tr.text}
4933
+ if (turnText.trim().length > 0 || inStreamRetryCount > 1) {
4934
+ if (inStreamRetryCount <= MAX_RETRIES) {
4935
+ inStreamRetryCount++;
4936
+ const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
4937
+ if (turnText.trim().length > 0) {
4938
+ modifiedHistory.push({ role: "agent", text: turnText });
4939
+ const recoveryText = "[SYSTEM: STREAM RECOVERY]\n- SEAMLESS CONTINUATION: Resume immediately. Pick up from last words with zero gap/disruption.\n- NO REPETITION: Do not repeat any text already written.\n- NO RE-THINK: Do not restart or open <think> if reasoning already started.\n- MID-TOOL SAFETY: If cutoff was mid-tool call, restart that tool call from start.\n- STEALTH: Do not mention/apologize for cutoff.\n- KEEP LENGTH: Maintain standard depth/length.";
4940
+ if (toolResults.length > 0) {
4941
+ toolResults.forEach((tr, idx) => {
4942
+ if (idx === toolResults.length - 1) {
4943
+ modifiedHistory.push({
4944
+ ...tr,
4945
+ text: `${tr.text}
4771
4946
 
4772
4947
  ${recoveryText}`
4773
- });
4774
- } else {
4775
- modifiedHistory.push(tr);
4776
- }
4777
- });
4778
- } else {
4779
- modifiedHistory.push({ role: "user", text: recoveryText });
4948
+ });
4949
+ } else {
4950
+ modifiedHistory.push(tr);
4951
+ }
4952
+ });
4953
+ } else {
4954
+ modifiedHistory.push({ role: "user", text: recoveryText });
4955
+ }
4956
+ accumulatedContext += turnText;
4780
4957
  }
4781
- accumulatedContext += turnText;
4782
- }
4783
- for (let i = waitTime / 1e3; i > 0; i--) {
4784
- yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
4785
- await new Promise((resolve) => setTimeout(resolve, 1e3));
4958
+ for (let i = waitTime / 1e3; i > 0; i--) {
4959
+ yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
4960
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
4961
+ }
4962
+ yield { type: "status", content: `Error Occured. Recovering Stream...` };
4963
+ } else {
4964
+ throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
4965
+ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4786
4966
  }
4787
- yield { type: "status", content: `Error Occured. Recovering Stream...` };
4788
4967
  } else {
4789
- throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
4790
- Error Log can be found in ${path14.join(LOGS_DIR, "agent", "error.log")}`);
4791
- }
4792
- } else {
4793
- if (retryCount <= MAX_RETRIES) {
4794
- retryCount++;
4795
- inStreamRetryCount = 1;
4796
- accumulatedContext = "";
4797
- const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 32e3);
4798
- isInitialAttempt = true;
4799
- yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
4800
- for (let i = waitTime / 1e3; i > 0; i--) {
4801
- yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${i}s]...` };
4802
- await new Promise((resolve) => setTimeout(resolve, 1e3));
4968
+ if (retryCount <= MAX_RETRIES) {
4969
+ retryCount++;
4970
+ inStreamRetryCount = 1;
4971
+ accumulatedContext = "";
4972
+ const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 32e3);
4973
+ isInitialAttempt = true;
4974
+ yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
4975
+ for (let i = waitTime / 1e3; i > 0; i--) {
4976
+ yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${i}s]...` };
4977
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
4978
+ }
4979
+ yield { type: "status", content: `Retrying Connection...` };
4980
+ } else {
4981
+ throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
4982
+ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4803
4983
  }
4804
- yield { type: "status", content: `Retrying Connection...` };
4805
- } else {
4806
- throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
4807
- Error Log can be found in ${path14.join(LOGS_DIR, "agent", "error.log")}`);
4808
4984
  }
4809
4985
  }
4810
4986
  }
4811
- }
4812
- if (lastUsage) {
4813
- await addToUsage("tokens", lastUsage.totalTokenCount || 0);
4814
- yield { type: "usage", content: lastUsage };
4815
- }
4816
- fullAgentResponseChunks.push(turnText);
4817
- let textToProcess = turnText;
4818
- const thinkMatch = turnText.match(/<think>([\s\S]*?)<\/think>/i);
4819
- if (thinkMatch) {
4820
- textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/i, "");
4821
- }
4822
- const signalSafeText = getSanitizedText(turnText);
4823
- const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
4824
- const shouldContinue = toolCallPointer > 0;
4825
- yield { type: "status", content: "Working..." };
4826
- const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
4827
- let isActuallyFinished = hasFinish && !shouldContinue;
4828
- if (isActuallyFinished) {
4829
- const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
4830
- const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
4831
- yield {
4832
- type: "interactive_turn_finished",
4833
- data: {
4834
- agentText,
4835
- fullAgentTextRaw,
4836
- history: [...modifiedHistory],
4837
- needTitle
4838
- }
4839
- };
4840
- const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
4841
- const finalWithTime = `${cleanedFullResponse}
4987
+ if (lastUsage) {
4988
+ await addToUsage("tokens", lastUsage.totalTokenCount || 0);
4989
+ yield { type: "usage", content: lastUsage };
4990
+ }
4991
+ fullAgentResponseChunks.push(turnText);
4992
+ let textToProcess = turnText;
4993
+ const thinkMatch = turnText.match(/<think>([\s\S]*?)<\/think>/i);
4994
+ if (thinkMatch) {
4995
+ textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/i, "");
4996
+ }
4997
+ const signalSafeText = getSanitizedText(turnText);
4998
+ const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
4999
+ const shouldContinue = toolCallPointer > 0;
5000
+ yield { type: "status", content: "Working..." };
5001
+ const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
5002
+ let isActuallyFinished = hasFinish && !shouldContinue;
5003
+ if (isActuallyFinished) {
5004
+ const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
5005
+ const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
5006
+ yield {
5007
+ type: "interactive_turn_finished",
5008
+ data: {
5009
+ agentText,
5010
+ fullAgentTextRaw,
5011
+ history: [...modifiedHistory],
5012
+ needTitle
5013
+ }
5014
+ };
5015
+ const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
5016
+ const finalWithTime = `${cleanedFullResponse}
4842
5017
 
4843
5018
  ${timestamp}`;
4844
- if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
4845
- modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
4846
- } else {
4847
- modifiedHistory.push({ role: "agent", text: finalWithTime });
5019
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
5020
+ modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
5021
+ } else {
5022
+ modifiedHistory.push({ role: "agent", text: finalWithTime });
5023
+ }
4848
5024
  }
4849
- }
4850
- if (isActuallyFinished) break;
4851
- const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
4852
- modifiedHistory.push({ role: "agent", text: nextAgentMsg });
4853
- if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
4854
- toolResults.forEach((tr) => modifiedHistory.push(tr));
4855
- } else {
4856
- if (wasToolCalledInLastLoop) {
4857
- modifiedHistory.push({ role: "user", text: `[SYSTEM] System executed the tool with no explicit result, continue with your task or use [turn: finish] if completed.` });
5025
+ if (isActuallyFinished) break;
5026
+ const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
5027
+ modifiedHistory.push({ role: "agent", text: nextAgentMsg });
5028
+ if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
5029
+ toolResults.forEach((tr) => modifiedHistory.push(tr));
4858
5030
  } else {
4859
- modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop ? " for current EFFORT_LEVEL" : ""}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
5031
+ if (wasToolCalledInLastLoop) {
5032
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] System executed the tool with no explicit result, continue with your task or use [turn: finish] if completed.` });
5033
+ } else {
5034
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] ${isStutteringLoop && !isThinkingLoop ? `STUTTERING DETECTED by Internal System. Re-calibrate your response & proceed.` : `${isThinkingLoop ? " OVER-THINKING" : " LOOP"} DETECTED by Internal System${isThinkingLoop ? " for current EFFORT_LEVEL" : ""}. ${isThinkingLoop ? "If you have planned the task, prioritize the execution/output. " : "If you have finished your task use [turn: finish] else continue."}`}` });
5035
+ }
5036
+ isThinkingLoop = false;
5037
+ isStutteringLoop = false;
5038
+ isGeneralLoop = false;
4860
5039
  }
4861
- isThinkingLoop = false;
4862
- isStutteringLoop = false;
4863
- isGeneralLoop = false;
5040
+ wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
4864
5041
  }
4865
- wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
5042
+ } finally {
5043
+ await RevertManager.commitTransaction();
4866
5044
  }
4867
5045
  yield { type: "status", content: null };
4868
5046
  };
@@ -5113,11 +5291,92 @@ var init_UpdateProcessor = __esm({
5113
5291
  }
5114
5292
  });
5115
5293
 
5294
+ // src/components/RevertModal.jsx
5295
+ import React10, { useState as useState7 } from "react";
5296
+ import { Box as Box10, Text as Text10, useInput as useInput4 } from "ink";
5297
+ function RevertModal({ prompts, onSelect, onClose }) {
5298
+ const [selectedIndex, setSelectedIndex] = useState7(0);
5299
+ useInput4((input, key) => {
5300
+ if (key.escape) onClose();
5301
+ if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
5302
+ if (key.downArrow) setSelectedIndex((prev) => Math.min(prompts.length - 1, prev + 1));
5303
+ if (key.return && prompts[selectedIndex]) onSelect(prompts[selectedIndex].id);
5304
+ });
5305
+ const s = emojiSpace(2);
5306
+ const MAX_VISIBLE = 10;
5307
+ let startIndex = 0;
5308
+ if (prompts.length > MAX_VISIBLE) {
5309
+ const half = Math.floor(MAX_VISIBLE / 2);
5310
+ startIndex = selectedIndex - half;
5311
+ if (startIndex < 0) {
5312
+ startIndex = 0;
5313
+ } else if (startIndex + MAX_VISIBLE > prompts.length) {
5314
+ startIndex = prompts.length - MAX_VISIBLE;
5315
+ }
5316
+ }
5317
+ const visiblePrompts = prompts.slice(startIndex, startIndex + MAX_VISIBLE);
5318
+ return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", padding: 0, width: 95 }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F504} CODEBASE TIME TRAVEL: SELECT UNDO POINT")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "Select a prompt to revert the codebase back to the state ", /* @__PURE__ */ React10.createElement(Text10, { bold: true, color: "blue" }, "immediately before"), " it was executed:")), prompts.length === 0 ? /* @__PURE__ */ React10.createElement(Box10, { paddingX: 2, paddingY: 1 }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, "No prompt checkpoints found for this session.")) : /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, startIndex > 0 && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 2, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, "\u25B2 (+", startIndex, " more prompts above)")), visiblePrompts.map((p, index) => {
5319
+ const actualIndex = startIndex + index;
5320
+ const isSelected = actualIndex === selectedIndex;
5321
+ const dateStr = formatDate2(p.timestamp);
5322
+ const fileCount = p.changes ? p.changes.length : 0;
5323
+ return /* @__PURE__ */ React10.createElement(
5324
+ Box10,
5325
+ {
5326
+ key: p.id,
5327
+ paddingX: 1,
5328
+ backgroundColor: isSelected ? "#1a2a3a" : void 0,
5329
+ width: "100%"
5330
+ },
5331
+ /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: isSelected ? "cyan" : "white", bold: isSelected }, isSelected ? "\u276F " : " ", '"', formatPromptPreview(p.prompt), '"', /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: !isSelected }, " [", dateStr, " \u2022 ", fileCount, " file(s) changed]")))
5332
+ );
5333
+ }), startIndex + MAX_VISIBLE < prompts.length && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 2, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true }, "\u25BC (+", prompts.length - (startIndex + MAX_VISIBLE), " more prompts below)"))), /* @__PURE__ */ React10.createElement(
5334
+ Box10,
5335
+ {
5336
+ marginTop: 1,
5337
+ paddingX: 1,
5338
+ borderStyle: "single",
5339
+ borderLeft: false,
5340
+ borderRight: false,
5341
+ borderBottom: false,
5342
+ borderColor: "cyan"
5343
+ },
5344
+ /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 Enter select undo point \u2022 Esc close")
5345
+ ));
5346
+ }
5347
+ function formatPromptPreview(prompt) {
5348
+ if (!prompt) return "";
5349
+ const firstLine = prompt.split("\n")[0] || "";
5350
+ const words = firstLine.split(/\s+/).filter(Boolean);
5351
+ if (words.length > 50) {
5352
+ return words.slice(0, 50).join(" ") + "...";
5353
+ }
5354
+ if (prompt.includes("\n")) {
5355
+ return firstLine + "...";
5356
+ }
5357
+ return firstLine;
5358
+ }
5359
+ function formatDate2(timestamp) {
5360
+ if (!timestamp) return "N/A";
5361
+ const d = new Date(timestamp);
5362
+ if (isNaN(d.getTime())) return "N/A";
5363
+ const pad = (n) => String(n).padStart(2, "0");
5364
+ const hh = pad(d.getHours());
5365
+ const min = pad(d.getMinutes());
5366
+ const sec = pad(d.getSeconds());
5367
+ return `${hh}:${min}:${sec}`;
5368
+ }
5369
+ var init_RevertModal = __esm({
5370
+ "src/components/RevertModal.jsx"() {
5371
+ init_terminal();
5372
+ }
5373
+ });
5374
+
5116
5375
  // src/utils/setup.js
5117
5376
  import puppeteer4 from "puppeteer";
5118
5377
  import { exec as exec3 } from "child_process";
5119
5378
  import { promisify } from "util";
5120
- import fs16 from "fs";
5379
+ import fs17 from "fs";
5121
5380
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
5122
5381
  var init_setup = __esm({
5123
5382
  "src/utils/setup.js"() {
@@ -5125,7 +5384,7 @@ var init_setup = __esm({
5125
5384
  checkPuppeteerReady = () => {
5126
5385
  try {
5127
5386
  const exePath = puppeteer4.executablePath();
5128
- const exists = exePath && fs16.existsSync(exePath);
5387
+ const exists = exePath && fs17.existsSync(exePath);
5129
5388
  if (exists) return true;
5130
5389
  } catch (e) {
5131
5390
  return false;
@@ -5156,28 +5415,28 @@ __export(app_exports, {
5156
5415
  default: () => App
5157
5416
  });
5158
5417
  import os4 from "os";
5159
- import React10, { useState as useState7, useEffect as useEffect6, useRef as useRef2, useMemo } from "react";
5160
- import { Box as Box10, Text as Text10, useInput as useInput4, useStdout } from "ink";
5418
+ import React11, { useState as useState8, useEffect as useEffect6, useRef as useRef2, useMemo } from "react";
5419
+ import { Box as Box11, Text as Text11, useInput as useInput5, useStdout } from "ink";
5161
5420
  import Spinner2 from "ink-spinner";
5162
- import fs17 from "fs-extra";
5163
- import path15 from "path";
5421
+ import fs18 from "fs-extra";
5422
+ import path16 from "path";
5164
5423
  import { exec as exec4 } from "child_process";
5165
5424
  import { fileURLToPath } from "url";
5166
5425
  import { MultilineInput } from "ink-multiline-input";
5167
5426
  import TextInput3 from "ink-text-input";
5168
5427
  import gradient from "gradient-string";
5169
5428
  function App({ args = [] }) {
5170
- const [confirmExit, setConfirmExit] = useState7(false);
5171
- const [exitCountdown, setExitCountdown] = useState7(10);
5429
+ const [confirmExit, setConfirmExit] = useState8(false);
5430
+ const [exitCountdown, setExitCountdown] = useState8(10);
5172
5431
  const { stdout } = useStdout();
5173
- const [input, setInput] = useState7("");
5174
- const [isExpanded, setIsExpanded] = useState7(false);
5175
- const [mode, setMode] = useState7("Flux");
5176
- const [terminalSize, setTerminalSize] = useState7({
5432
+ const [input, setInput] = useState8("");
5433
+ const [isExpanded, setIsExpanded] = useState8(false);
5434
+ const [mode, setMode] = useState8("Flux");
5435
+ const [terminalSize, setTerminalSize] = useState8({
5177
5436
  columns: stdout?.columns || 80,
5178
5437
  rows: stdout?.rows || 24
5179
5438
  });
5180
- const [selectedIndex, setSelectedIndex] = useState7(0);
5439
+ const [selectedIndex, setSelectedIndex] = useState8(0);
5181
5440
  const persistedModelRef = useRef2(null);
5182
5441
  const parsedArgs = useMemo(() => {
5183
5442
  const parsed = {};
@@ -5281,37 +5540,37 @@ function App({ args = [] }) {
5281
5540
  stdout.off("resize", handleResize);
5282
5541
  };
5283
5542
  }, [stdout]);
5284
- const [thinkingLevel, setThinkingLevel] = useState7("Medium");
5285
- const [latestVer, setLatestVer] = useState7(null);
5286
- const [showFullThinking, setShowFullThinking] = useState7(false);
5287
- const [activeModel, setActiveModel] = useState7("gemma-4-31b-it");
5288
- const [janitorModel, setJanitorModel] = useState7("gemma-4-26b-a4b-it");
5289
- const [isInitializing, setIsInitializing] = useState7(true);
5290
- const [apiKey, setApiKey] = useState7(null);
5291
- const [tempKey, setTempKey] = useState7("");
5292
- const [activeView, setActiveView] = useState7("chat");
5293
- const [apiTier, setApiTier] = useState7("Free");
5294
- const [quotas, setQuotas] = useState7({ agentLimit: 1500, backgroundLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
5295
- const [inputConfig, setInputConfig] = useState7(null);
5296
- const [systemSettings, setSystemSettings] = useState7({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
5297
- const [profileData, setProfileData] = useState7({ name: null, nickname: null, instructions: null });
5298
- const [imageSettings, setImageSettings] = useState7({ keyType: "Default", quality: "Low-High", apiKey: "" });
5299
- const [sessionStats, setSessionStats] = useState7({ tokens: 0 });
5300
- const [sessionAgentCalls, setSessionAgentCalls] = useState7(0);
5301
- const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState7(0);
5302
- const [sessionTotalTokens, setSessionTotalTokens] = useState7(0);
5303
- const [sessionToolSuccess, setSessionToolSuccess] = useState7(0);
5304
- const [sessionToolFailure, setSessionToolFailure] = useState7(0);
5305
- const [sessionToolDenied, setSessionToolDenied] = useState7(0);
5306
- const [sessionApiTime, setSessionApiTime] = useState7(0);
5307
- const [sessionToolTime, setSessionToolTime] = useState7(0);
5308
- const [sessionImageCount, setSessionImageCount] = useState7(0);
5309
- const [sessionImageCredits, setSessionImageCredits] = useState7(0);
5310
- const [dailyUsage, setDailyUsage] = useState7(null);
5311
- const [chatId, setChatId] = useState7(generateChatId());
5312
- const [activeCommand, setActiveCommand] = useState7(null);
5313
- const [execOutput, setExecOutput] = useState7("");
5314
- const [isTerminalFocused, setIsTerminalFocused] = useState7(false);
5543
+ const [thinkingLevel, setThinkingLevel] = useState8("Medium");
5544
+ const [latestVer, setLatestVer] = useState8(null);
5545
+ const [showFullThinking, setShowFullThinking] = useState8(false);
5546
+ const [activeModel, setActiveModel] = useState8("gemma-4-31b-it");
5547
+ const [janitorModel, setJanitorModel] = useState8("gemma-4-26b-a4b-it");
5548
+ const [isInitializing, setIsInitializing] = useState8(true);
5549
+ const [apiKey, setApiKey] = useState8(null);
5550
+ const [tempKey, setTempKey] = useState8("");
5551
+ const [activeView, setActiveView] = useState8("chat");
5552
+ const [apiTier, setApiTier] = useState8("Free");
5553
+ const [quotas, setQuotas] = useState8({ agentLimit: 1500, backgroundLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
5554
+ const [inputConfig, setInputConfig] = useState8(null);
5555
+ const [systemSettings, setSystemSettings] = useState8({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
5556
+ const [profileData, setProfileData] = useState8({ name: null, nickname: null, instructions: null });
5557
+ const [imageSettings, setImageSettings] = useState8({ keyType: "Default", quality: "Low-High", apiKey: "" });
5558
+ const [sessionStats, setSessionStats] = useState8({ tokens: 0 });
5559
+ const [sessionAgentCalls, setSessionAgentCalls] = useState8(0);
5560
+ const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState8(0);
5561
+ const [sessionTotalTokens, setSessionTotalTokens] = useState8(0);
5562
+ const [sessionToolSuccess, setSessionToolSuccess] = useState8(0);
5563
+ const [sessionToolFailure, setSessionToolFailure] = useState8(0);
5564
+ const [sessionToolDenied, setSessionToolDenied] = useState8(0);
5565
+ const [sessionApiTime, setSessionApiTime] = useState8(0);
5566
+ const [sessionToolTime, setSessionToolTime] = useState8(0);
5567
+ const [sessionImageCount, setSessionImageCount] = useState8(0);
5568
+ const [sessionImageCredits, setSessionImageCredits] = useState8(0);
5569
+ const [dailyUsage, setDailyUsage] = useState8(null);
5570
+ const [chatId, setChatId] = useState8(generateChatId());
5571
+ const [activeCommand, setActiveCommand] = useState8(null);
5572
+ const [execOutput, setExecOutput] = useState8("");
5573
+ const [isTerminalFocused, setIsTerminalFocused] = useState8(false);
5315
5574
  useEffect6(() => {
5316
5575
  if (apiTier !== "Free" && activeModel === "gemma-4-31b-it") {
5317
5576
  setActiveModel("gemini-3-flash-preview");
@@ -5341,9 +5600,9 @@ function App({ args = [] }) {
5341
5600
  useEffect6(() => {
5342
5601
  execOutputRef.current = execOutput;
5343
5602
  }, [execOutput]);
5344
- const [autoAcceptWrites, setAutoAcceptWrites] = useState7(false);
5345
- const [pendingApproval, setPendingApproval] = useState7(null);
5346
- const [pendingAsk, setPendingAsk] = useState7(null);
5603
+ const [autoAcceptWrites, setAutoAcceptWrites] = useState8(false);
5604
+ const [pendingApproval, setPendingApproval] = useState8(null);
5605
+ const [pendingAsk, setPendingAsk] = useState8(null);
5347
5606
  const formatDuration = (totalSecs) => {
5348
5607
  const h = Math.floor(totalSecs / 3600);
5349
5608
  const m = Math.floor(totalSecs % 3600 / 60);
@@ -5358,15 +5617,18 @@ function App({ args = [] }) {
5358
5617
  if (ms < 1e3) return `${ms}ms`;
5359
5618
  return formatDuration(Math.floor(ms / 1e3));
5360
5619
  };
5361
- const [statusText, setStatusText] = useState7(null);
5362
- const [isSpinnerActive, setIsSpinnerActive] = useState7(true);
5363
- const [isProcessing, setIsProcessing] = useState7(false);
5364
- const [escPressed, setEscPressed] = useState7(false);
5365
- const [escTimer, setEscTimer] = useState7(null);
5366
- const [queuedPrompt, setQueuedPrompt] = useState7(null);
5367
- const [resolutionData, setResolutionData] = useState7(null);
5368
- const [tempModelOverride, setTempModelOverride] = useState7(null);
5369
- const [messages, setMessages] = useState7(() => {
5620
+ const [statusText, setStatusText] = useState8(null);
5621
+ const [isSpinnerActive, setIsSpinnerActive] = useState8(true);
5622
+ const [isProcessing, setIsProcessing] = useState8(false);
5623
+ const [escPressed, setEscPressed] = useState8(false);
5624
+ const [escTimer, setEscTimer] = useState8(null);
5625
+ const [escPressCount, setEscPressCount] = useState8(0);
5626
+ const [recentPrompts, setRecentPrompts] = useState8([]);
5627
+ const escDoubleTimerRef = useRef2(null);
5628
+ const [queuedPrompt, setQueuedPrompt] = useState8(null);
5629
+ const [resolutionData, setResolutionData] = useState8(null);
5630
+ const [tempModelOverride, setTempModelOverride] = useState8(null);
5631
+ const [messages, setMessages] = useState8(() => {
5370
5632
  const logoMsg = { id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true };
5371
5633
  const welcomeMsg = { id: "welcome", role: "system", text: "\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true };
5372
5634
  const isHomeDir = process.cwd() === os4.homedir();
@@ -5405,7 +5667,7 @@ function App({ args = [] }) {
5405
5667
  return msgs;
5406
5668
  });
5407
5669
  const queuedPromptRef = useRef2(null);
5408
- const [completedIndex, setCompletedIndex] = useState7(messages.length);
5670
+ const [completedIndex, setCompletedIndex] = useState8(messages.length);
5409
5671
  const windowedHistory = useMemo(() => {
5410
5672
  const MAX_HISTORY_LINES = 2e3;
5411
5673
  const width = terminalSize.columns || 80;
@@ -5440,7 +5702,7 @@ function App({ args = [] }) {
5440
5702
  return acc + Math.max(1, Math.ceil(line.length / wrapWidth));
5441
5703
  }, 0);
5442
5704
  const maxLines = Math.max(1, wrappedLinesCount);
5443
- useInput4((inputText, key) => {
5705
+ useInput5((inputText, key) => {
5444
5706
  if (key.tab && activeCommand) {
5445
5707
  setIsTerminalFocused((prev) => !prev);
5446
5708
  return;
@@ -5485,8 +5747,36 @@ function App({ args = [] }) {
5485
5747
  setEscPressed(false);
5486
5748
  if (escTimer) clearTimeout(escTimer);
5487
5749
  }
5488
- } else if (activeView !== "chat") {
5489
- setActiveView("chat");
5750
+ } else {
5751
+ if (activeView === "revert") {
5752
+ setActiveView("chat");
5753
+ setEscPressCount(0);
5754
+ } else if (activeView !== "chat") {
5755
+ setActiveView("chat");
5756
+ } else {
5757
+ setEscPressCount((prev) => {
5758
+ const nextCount = prev + 1;
5759
+ if (nextCount === 1) {
5760
+ if (escDoubleTimerRef.current) clearTimeout(escDoubleTimerRef.current);
5761
+ escDoubleTimerRef.current = setTimeout(() => setEscPressCount(0), 1e3);
5762
+ } else if (nextCount === 2) {
5763
+ if (escDoubleTimerRef.current) clearTimeout(escDoubleTimerRef.current);
5764
+ setEscPressCount(0);
5765
+ RevertManager.getChatHistory(chatId).then((prompts) => {
5766
+ if (prompts.length > 0) {
5767
+ setRecentPrompts(prompts.reverse());
5768
+ setActiveView("revert");
5769
+ } else {
5770
+ setMessages((prev2) => {
5771
+ setCompletedIndex(prev2.length + 1);
5772
+ return [...prev2, { id: "revert-empty-" + Date.now(), role: "system", text: "\u2139\uFE0F No revert checkpoints found for this session.", isMeta: true }];
5773
+ });
5774
+ }
5775
+ });
5776
+ }
5777
+ return nextCount;
5778
+ });
5779
+ }
5490
5780
  }
5491
5781
  }
5492
5782
  if (suggestions.length > 0 && activeView === "chat") {
@@ -5707,6 +5997,7 @@ function App({ args = [] }) {
5707
5997
  { cmd: "/help", desc: "Show all available commands" },
5708
5998
  { cmd: "/clear", desc: "Clear terminal screen" },
5709
5999
  { cmd: "/resume", desc: "Load previous session" },
6000
+ { cmd: "/revert", desc: "Revert codebase back to a checkpoint" },
5710
6001
  { cmd: "/save", desc: "Force save current chat" },
5711
6002
  { cmd: "/export", desc: "Export current chat in a .txt file" },
5712
6003
  { cmd: "/chats", desc: "List all chat sessions" },
@@ -5889,6 +6180,21 @@ ${hintText}`, color: "magenta" }];
5889
6180
  setIsExpanded(false);
5890
6181
  break;
5891
6182
  }
6183
+ case "/revert": {
6184
+ RevertManager.getChatHistory(chatId).then((prompts) => {
6185
+ if (prompts.length > 0) {
6186
+ setRecentPrompts(prompts.reverse());
6187
+ setActiveView("revert");
6188
+ } else {
6189
+ const s2 = emojiSpace(2);
6190
+ setMessages((prev) => {
6191
+ setCompletedIndex(prev.length + 1);
6192
+ return [...prev, { id: "revert-empty-" + Date.now(), role: "system", text: `No revert checkpoints found for this session.`, isMeta: true }];
6193
+ });
6194
+ }
6195
+ });
6196
+ break;
6197
+ }
5892
6198
  case "/mode": {
5893
6199
  if (parts[1]) {
5894
6200
  const newMode = parts[1].toLowerCase() === "flow" ? "Flow" : "Flux";
@@ -6124,7 +6430,7 @@ ${hintText}`, color: "magenta" }];
6124
6430
  }
6125
6431
  case "/export": {
6126
6432
  const exportFile = `export-fluxflow-${chatId}.txt`;
6127
- const exportPath = path15.join(process.cwd(), exportFile);
6433
+ const exportPath = path16.join(process.cwd(), exportFile);
6128
6434
  const exportLines = [];
6129
6435
  let insideAgentBlock = false;
6130
6436
  for (let i = 0; i < messages.length; i++) {
@@ -6175,7 +6481,7 @@ ${hintText}`, color: "magenta" }];
6175
6481
  }
6176
6482
  }
6177
6483
  const fileContent = exportLines.join("\n");
6178
- fs17.writeFileSync(exportPath, fileContent, "utf8");
6484
+ fs18.writeFileSync(exportPath, fileContent, "utf8");
6179
6485
  setMessages((prev) => {
6180
6486
  setCompletedIndex(prev.length + 1);
6181
6487
  return [...prev, {
@@ -6211,12 +6517,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
6211
6517
  setCompletedIndex(prev.length + 1);
6212
6518
  return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset...", isMeta: true }];
6213
6519
  });
6214
- if (fs17.existsSync(LOGS_DIR)) fs17.removeSync(LOGS_DIR);
6215
- if (fs17.existsSync(SECRET_DIR)) fs17.removeSync(SECRET_DIR);
6216
- if (fs17.existsSync(SETTINGS_FILE)) fs17.removeSync(SETTINGS_FILE);
6520
+ if (fs18.existsSync(LOGS_DIR)) fs18.removeSync(LOGS_DIR);
6521
+ if (fs18.existsSync(SECRET_DIR)) fs18.removeSync(SECRET_DIR);
6522
+ if (fs18.existsSync(SETTINGS_FILE)) fs18.removeSync(SETTINGS_FILE);
6217
6523
  try {
6218
- const items = fs17.readdirSync(FLUXFLOW_DIR);
6219
- if (items.length === 0) fs17.removeSync(FLUXFLOW_DIR);
6524
+ const items = fs18.readdirSync(FLUXFLOW_DIR);
6525
+ if (items.length === 0) fs18.removeSync(FLUXFLOW_DIR);
6220
6526
  } catch (e) {
6221
6527
  }
6222
6528
  setTimeout(() => {
@@ -6273,14 +6579,14 @@ ${list || "No saved chats found."}`, isMeta: true }];
6273
6579
  # SKILLS & WORKFLOWS
6274
6580
  - [Define custom step-by-step recipes for this project here]
6275
6581
  `;
6276
- const filePath = path15.join(process.cwd(), "FluxFlow.md");
6277
- if (fs17.pathExistsSync(filePath)) {
6582
+ const filePath = path16.join(process.cwd(), "FluxFlow.md");
6583
+ if (fs18.pathExistsSync(filePath)) {
6278
6584
  setMessages((prev) => {
6279
6585
  setCompletedIndex(prev.length + 1);
6280
6586
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
6281
6587
  });
6282
6588
  } else {
6283
- fs17.writeFileSync(filePath, template);
6589
+ fs18.writeFileSync(filePath, template);
6284
6590
  setMessages((prev) => {
6285
6591
  setCompletedIndex(prev.length + 1);
6286
6592
  return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "\u2705 [SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
@@ -6709,7 +7015,7 @@ Selection: ${val}`,
6709
7015
  const renderActiveView = () => {
6710
7016
  switch (activeView) {
6711
7017
  case "settings":
6712
- return /* @__PURE__ */ React10.createElement(
7018
+ return /* @__PURE__ */ React11.createElement(
6713
7019
  CommandMenu,
6714
7020
  {
6715
7021
  title: "System Settings",
@@ -6777,7 +7083,7 @@ Selection: ${val}`,
6777
7083
  }
6778
7084
  );
6779
7085
  case "apiTier":
6780
- return /* @__PURE__ */ React10.createElement(
7086
+ return /* @__PURE__ */ React11.createElement(
6781
7087
  CommandMenu,
6782
7088
  {
6783
7089
  title: `API Tier: ${apiTier}`,
@@ -6810,7 +7116,7 @@ Selection: ${val}`,
6810
7116
  }
6811
7117
  );
6812
7118
  case "input":
6813
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "\u{1F527} DATA CONFIGURATION")), inputConfig?.note && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", dimColor: true, italic: true }, inputConfig.note)), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, inputConfig?.label, " "), /* @__PURE__ */ React10.createElement(
7119
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "magenta", bold: true }, "\u{1F527} DATA CONFIGURATION")), inputConfig?.note && /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", dimColor: true, italic: true }, inputConfig.note)), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, flexDirection: "row" }, /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, inputConfig?.label, " "), /* @__PURE__ */ React11.createElement(
6814
7120
  TextInput3,
6815
7121
  {
6816
7122
  value: inputConfig?.value || "",
@@ -6863,11 +7169,11 @@ Selection: ${val}`,
6863
7169
  }
6864
7170
  }
6865
7171
  }
6866
- )), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
7172
+ )), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
6867
7173
  case "stats":
6868
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 23 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, dailyUsage?.imageCalls?.length || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, Number(((dailyUsage?.imageCalls?.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 25 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " "), /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " )"))), /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
7174
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, width: Math.min(100, (stdout?.columns || 100) - 2) }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "white", bold: true, underline: true }, "SESSION TELEMETRY")), /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Session Duration:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(Date.now() - SESSION_START_TIME))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionAgentCalls)), /* @__PURE__ */ React11.createElement(Box11, { marginLeft: 2 }, /* @__PURE__ */ React11.createElement(Box11, { width: 23 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(sessionApiTime))), /* @__PURE__ */ React11.createElement(Box11, { marginLeft: 2 }, /* @__PURE__ */ React11.createElement(Box11, { width: 23 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(sessionToolTime))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionBackgroundCalls)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tool Calls (Sess):")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( "), /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "\u2713 ", sessionToolSuccess), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " "), /* @__PURE__ */ React11.createElement(Text11, { color: "yellow" }, "\u2298 ", sessionToolDenied), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " "), /* @__PURE__ */ React11.createElement(Text11, { color: "red" }, "\u2715 ", sessionToolFailure), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " )"))), /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "white", bold: true, underline: true }, "DAILY USAGE TRACKER"), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Wall Time Today:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatDuration(dailyUsage?.duration || 0))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Agent Interactions:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, dailyUsage?.agent || 0)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Background Tasks:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, dailyUsage?.background || 0)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tokens Used Today:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatTokens(dailyUsage?.tokens || 0))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Images Made Today:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, dailyUsage?.imageCalls?.length || 0)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Image Credits Today:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, Number(((dailyUsage?.imageCalls?.reduce((sum, c) => sum + c.cost, 0) || 0) * 1e3).toFixed(0)), " credits")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 25 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tool Calls Today:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, (dailyUsage?.toolSuccess || 0) + (dailyUsage?.toolFailure || 0) + (dailyUsage?.toolDenied || 0), " ( "), /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "\u2713 ", dailyUsage?.toolSuccess || 0), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " "), /* @__PURE__ */ React11.createElement(Text11, { color: "yellow" }, "\u2298 ", dailyUsage?.toolDenied || 0), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " "), /* @__PURE__ */ React11.createElement(Text11, { color: "red" }, "\u2715 ", dailyUsage?.toolFailure || 0), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " )"))), /* @__PURE__ */ React11.createElement(Text11, { dimColor: true, marginTop: 1, italic: true }, "(Press ESC to return to chat)"));
6869
7175
  case "autoExecDanger":
6870
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7176
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: AUTO-EXEC MODE"), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "Turning this ON allows the agent to execute terminal commands automatically without requiring your approval for each step."), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 The agent may execute destructive commands (rm -rf, etc.) by mistake."), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 Unintended system changes if the agent hallucinates a path or command."), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 Reduced control over the agent's step-by-step decision making."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
6871
7177
  CommandMenu,
6872
7178
  {
6873
7179
  title: "Confirm Intent",
@@ -6884,7 +7190,7 @@ Selection: ${val}`,
6884
7190
  }
6885
7191
  )));
6886
7192
  case "externalDanger":
6887
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: EXTERNAL WORKSPACE ACCESS"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "Turning this ON allows the agent to execute tools (Read/Write/Exec) outside of the current active workspace directory."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Access to sensitive system files (SSH keys, Browser data, etc.)"), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Potential for accidental or malicious deletion of OS-critical files."), /* @__PURE__ */ React10.createElement(Text10, null, "\u2022 Unauthorized script execution across your entire file system."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7193
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true, underline: true }, "\u26A0\uFE0F SECURITY WARNING: EXTERNAL WORKSPACE ACCESS"), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "Turning this ON allows the agent to execute tools (Read/Write/Exec) outside of the current active workspace directory."), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, color: "yellow" }, "RISKS INVOLVED:"), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 Access to sensitive system files (SSH keys, Browser data, etc.)"), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 Potential for accidental or malicious deletion of OS-critical files."), /* @__PURE__ */ React11.createElement(Text11, null, "\u2022 Unauthorized script execution across your entire file system."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
6888
7194
  CommandMenu,
6889
7195
  {
6890
7196
  title: "Confirm Intent",
@@ -6901,7 +7207,7 @@ Selection: ${val}`,
6901
7207
  }
6902
7208
  )));
6903
7209
  case "doubleDanger":
6904
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u26D4 CRITICAL SECURITY WARNING: COMBINED SYSTEM RISK"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "You are attempting to enable BOTH [Auto-Exec] and [External Workspace Access] simultaneously."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "red", bold: true }, "THIS IS NOT RECOMMENDED."), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1, color: "yellow" }, "THE CRITICAL RISK:"), /* @__PURE__ */ React10.createElement(Text10, null, "The agent will have the power to execute any command across your entire system WITHOUT your approval or supervision."), /* @__PURE__ */ React10.createElement(Text10, { color: "red", italic: true, marginTop: 1 }, "A single hallucination or error could result in full system wipe or data theft."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7210
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true, underline: true }, "\u26D4 CRITICAL SECURITY WARNING: COMBINED SYSTEM RISK"), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "You are attempting to enable BOTH [Auto-Exec] and [External Workspace Access] simultaneously."), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, color: "red", bold: true }, "THIS IS NOT RECOMMENDED."), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1, color: "yellow" }, "THE CRITICAL RISK:"), /* @__PURE__ */ React11.createElement(Text11, null, "The agent will have the power to execute any command across your entire system WITHOUT your approval or supervision."), /* @__PURE__ */ React11.createElement(Text11, { color: "red", italic: true, marginTop: 1 }, "A single hallucination or error could result in full system wipe or data theft."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
6905
7211
  CommandMenu,
6906
7212
  {
6907
7213
  title: "Final Confirmation",
@@ -6918,7 +7224,7 @@ Selection: ${val}`,
6918
7224
  }
6919
7225
  )));
6920
7226
  case "key":
6921
- return /* @__PURE__ */ React10.createElement(
7227
+ return /* @__PURE__ */ React11.createElement(
6922
7228
  CommandMenu,
6923
7229
  {
6924
7230
  title: "\u{1F511} API KEY MANAGEMENT",
@@ -6942,10 +7248,10 @@ Selection: ${val}`,
6942
7248
  }
6943
7249
  );
6944
7250
  case "deleteKey":
6945
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, (() => {
7251
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, (() => {
6946
7252
  const s = emojiSpace(2);
6947
- return /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u26D4", s, "DANGER: PURGE API KEY");
6948
- })(), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7253
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true }, "\u26D4", s, "DANGER: PURGE API KEY");
7254
+ })(), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "This will permanently delete the saved API key from the project vault. You will need to enter it again to use Flux."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
6949
7255
  CommandMenu,
6950
7256
  {
6951
7257
  title: "Are you absolutely sure?",
@@ -6969,7 +7275,7 @@ Selection: ${val}`,
6969
7275
  case "exit":
6970
7276
  return null;
6971
7277
  case "ask":
6972
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%" }, /* @__PURE__ */ React10.createElement(
7278
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%" }, /* @__PURE__ */ React11.createElement(
6973
7279
  AskUserModal_default,
6974
7280
  {
6975
7281
  question: pendingAsk?.question,
@@ -6983,8 +7289,62 @@ Selection: ${val}`,
6983
7289
  }
6984
7290
  }
6985
7291
  ));
7292
+ case "revert":
7293
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
7294
+ RevertModal,
7295
+ {
7296
+ prompts: recentPrompts,
7297
+ onSelect: async (txId) => {
7298
+ try {
7299
+ const result = await RevertManager.rollbackToBefore(txId);
7300
+ if (result.success) {
7301
+ const { targetPrompt } = result;
7302
+ const targetIdx = messages.findIndex(
7303
+ (m) => m.role === "user" && m.text && (m.text.startsWith(targetPrompt) || m.text.includes(targetPrompt))
7304
+ );
7305
+ let newMsgs = [...messages];
7306
+ if (targetIdx !== -1) {
7307
+ newMsgs = messages.slice(0, targetIdx);
7308
+ }
7309
+ setMessages(newMsgs);
7310
+ setCompletedIndex(newMsgs.length);
7311
+ setInput(targetPrompt);
7312
+ setIsExpanded(targetPrompt.split("\n").length > 2);
7313
+ const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && !m.isMeta);
7314
+ await saveChat(chatId, null, historyToSave);
7315
+ const s = emojiSpace(2);
7316
+ setMessages((prev) => {
7317
+ const finalMsgs = [...prev, {
7318
+ id: "revert-ok-" + Date.now(),
7319
+ role: "system",
7320
+ text: `\u{1F504}${s}[TIME TRAVEL] Codebase rolled back successfully! Reverted prompt loaded to input box.`,
7321
+ isMeta: true
7322
+ }];
7323
+ setCompletedIndex(finalMsgs.length);
7324
+ return finalMsgs;
7325
+ });
7326
+ setActiveView("chat");
7327
+ }
7328
+ } catch (err) {
7329
+ const s = emojiSpace(2);
7330
+ setMessages((prev) => {
7331
+ const finalMsgs = [...prev, {
7332
+ id: "revert-err-" + Date.now(),
7333
+ role: "system",
7334
+ text: `\u274C${s}[TIME TRAVEL ERROR] Failed to rollback: ${err.message}`,
7335
+ isMeta: true
7336
+ }];
7337
+ setCompletedIndex(finalMsgs.length);
7338
+ return finalMsgs;
7339
+ });
7340
+ setActiveView("chat");
7341
+ }
7342
+ },
7343
+ onClose: () => setActiveView("chat")
7344
+ }
7345
+ ));
6986
7346
  case "resume":
6987
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(
7347
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
6988
7348
  ResumeModal,
6989
7349
  {
6990
7350
  onSelect: async (id) => {
@@ -7014,9 +7374,9 @@ Selection: ${val}`,
7014
7374
  }
7015
7375
  ));
7016
7376
  case "memory":
7017
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
7377
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
7018
7378
  case "profile":
7019
- return /* @__PURE__ */ React10.createElement(
7379
+ return /* @__PURE__ */ React11.createElement(
7020
7380
  ProfileForm,
7021
7381
  {
7022
7382
  initialData: profileData,
@@ -7029,7 +7389,7 @@ Selection: ${val}`,
7029
7389
  }
7030
7390
  );
7031
7391
  case "resolution":
7032
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(
7392
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
7033
7393
  ResolutionModal,
7034
7394
  {
7035
7395
  data: resolutionData,
@@ -7048,15 +7408,15 @@ Selection: ${val}`,
7048
7408
  }
7049
7409
  ));
7050
7410
  case "approval":
7051
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true, underline: true }, "\u{1F510} SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React10.createElement(Text10, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
7411
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "yellow", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", bold: true, underline: true }, "\u{1F510} SECURITY GATE: FILE WRITE PERMISSION"), /* @__PURE__ */ React11.createElement(Text11, { marginTop: 1 }, "The agent is attempting to modify: ", /* @__PURE__ */ React11.createElement(Text11, { color: "cyan" }, parseArgs(pendingApproval?.args || "{}").path || "Unknown File")), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1, borderStyle: "single", borderColor: "#333", paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray" }, "--- PROPOSED CONTENT / DIFF ---"), (() => {
7052
7412
  const args2 = parseArgs(pendingApproval?.args || "{}");
7053
7413
  const oldVal = args2.TargetContent || args2.content_to_replace || null;
7054
7414
  const newVal = args2.content || args2.ReplacementContent || args2.content_to_add || args2.replacementContent || null;
7055
7415
  if (oldVal && newVal) {
7056
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal.replace(/\[\/n\]?/g, "\\n"))));
7416
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text11, { color: "red", wrap: "anywhere", bold: true }, "- ", oldVal)), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "green", wrap: "anywhere", bold: true }, "+ ", newVal.replace(/\[\/n\]?/g, "\\n"))));
7057
7417
  }
7058
- return /* @__PURE__ */ React10.createElement(Text10, { color: "white", wrap: "anywhere" }, newVal.replace(/\[\/n\]?/g, "\\n") || "Updating file content...");
7059
- })()), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7418
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "white", wrap: "anywhere" }, newVal.replace(/\[\/n\]?/g, "\\n") || "Updating file content...");
7419
+ })()), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
7060
7420
  CommandMenu,
7061
7421
  {
7062
7422
  title: "Action Required",
@@ -7075,7 +7435,7 @@ Selection: ${val}`,
7075
7435
  }
7076
7436
  )));
7077
7437
  case "updateManager":
7078
- return /* @__PURE__ */ React10.createElement(
7438
+ return /* @__PURE__ */ React11.createElement(
7079
7439
  CommandMenu,
7080
7440
  {
7081
7441
  title: "Select Preferred Update Manager",
@@ -7112,7 +7472,7 @@ Selection: ${val}`,
7112
7472
  }
7113
7473
  );
7114
7474
  case "update":
7115
- return /* @__PURE__ */ React10.createElement(
7475
+ return /* @__PURE__ */ React11.createElement(
7116
7476
  UpdateProcessor_default,
7117
7477
  {
7118
7478
  latest: latestVer,
@@ -7138,7 +7498,7 @@ Selection: ${val}`,
7138
7498
  }
7139
7499
  );
7140
7500
  case "terminalApproval":
7141
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true, underline: true }, "\u{1F510} SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "Agent requested to run: ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(
7501
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true, underline: true }, "\u{1F510} SECURITY GATE: TERMINAL COMMAND OVERSIGHT"), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, null, "Agent requested to run: ", /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", bold: true }, parseArgs(pendingApproval?.args || "{}").command || "Unknown Command"))), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
7142
7502
  CommandMenu,
7143
7503
  {
7144
7504
  title: "Risk Assessment Required",
@@ -7154,8 +7514,8 @@ Selection: ${val}`,
7154
7514
  }
7155
7515
  )));
7156
7516
  default:
7157
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, null, statusText ? /* @__PURE__ */ React10.createElement(Box10, null, isSpinnerActive && /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, /* @__PURE__ */ React10.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, italic: true }, isSpinnerActive ? " " : "", statusText.toUpperCase())) : /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", dimColor: true, italic: true }, "READY FOR COMMAND...")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React10.createElement(
7158
- Box10,
7517
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", marginTop: 1, flexShrink: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, null, statusText ? /* @__PURE__ */ React11.createElement(Box11, null, isSpinnerActive && /* @__PURE__ */ React11.createElement(Text11, { color: "magenta" }, /* @__PURE__ */ React11.createElement(Spinner2, { type: "dots" })), /* @__PURE__ */ React11.createElement(Text11, { color: "magenta", bold: true, italic: true }, isSpinnerActive ? " " : "", statusText.toUpperCase())) : /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", dimColor: true, italic: true }, "READY FOR COMMAND...")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", bold: true }, "[ "), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, tempModelOverride || activeModel), /* @__PURE__ */ React11.createElement(Text11, { color: "gray", bold: true }, " ]"))), /* @__PURE__ */ React11.createElement(
7518
+ Box11,
7159
7519
  {
7160
7520
  borderStyle: "round",
7161
7521
  borderColor: isProcessing ? "magenta" : "cyan",
@@ -7163,7 +7523,7 @@ Selection: ${val}`,
7163
7523
  paddingY: 0,
7164
7524
  width: "100%"
7165
7525
  },
7166
- /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F4A0} ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true }, "[PASTED ", maxLines, " LINES]")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React10.createElement(
7526
+ /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", width: "100%" }, maxLines > 2 && !isExpanded ? /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "row", width: "100%", paddingY: 0, height: 1, overflow: "hidden" }, /* @__PURE__ */ React11.createElement(Box11, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, "\u{1F4A0} ")), /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1, flexDirection: "row" }, /* @__PURE__ */ React11.createElement(Box11, { flexShrink: 0 }, /* @__PURE__ */ React11.createElement(Text11, { color: "magenta", bold: true }, "[PASTED ", maxLines, " LINES]")), /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1, marginLeft: 1 }, /* @__PURE__ */ React11.createElement(
7167
7527
  MultilineInput,
7168
7528
  {
7169
7529
  value: "",
@@ -7180,7 +7540,7 @@ Selection: ${val}`,
7180
7540
  newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
7181
7541
  }
7182
7542
  }
7183
- )))) : /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React10.createElement(Text10, { color: isProcessing ? "magenta" : "cyan", bold: true }, isProcessing ? "\u2726 " : "\u{1F4A0} ")), /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React10.createElement(Box10, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : /* @__PURE__ */ React10.createElement(Text10, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Send message or /cmd... (${terminalEnv.shortcut} for newline)` : " Enter a prompt to steer the agent.")), /* @__PURE__ */ React10.createElement(
7543
+ )))) : /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "row", width: "100%", paddingY: 0 }, /* @__PURE__ */ React11.createElement(Box11, { flexShrink: 0, width: 4 }, /* @__PURE__ */ React11.createElement(Text11, { color: isProcessing ? "magenta" : "cyan", bold: true }, isProcessing ? "\u2726 " : "\u{1F4A0} ")), /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1 }, /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1, position: "relative" }, input === "" && /* @__PURE__ */ React11.createElement(Box11, { position: "absolute", paddingLeft: 0 }, activeCommand && !isTerminalFocused ? /* @__PURE__ */ React11.createElement(Text11, { color: "yellow" }, " Press TAB to interact with terminal...") : activeCommand && isTerminalFocused ? /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", bold: true }, " [ TERMINAL FOCUSED ] Type to interact, press TAB to exit...") : escPressCount === 1 ? /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, " Press ESC again to revert codebase to checkpoint...") : /* @__PURE__ */ React11.createElement(Text11, { color: "gray" }, escPressed ? " Press ESC again to cancel the request." : !isProcessing ? ` Send message or /cmd... (${terminalEnv.shortcut} for newline)` : " Enter a prompt to steer the agent.")), /* @__PURE__ */ React11.createElement(
7184
7544
  MultilineInput,
7185
7545
  {
7186
7546
  focus: !isTerminalFocused,
@@ -7200,14 +7560,14 @@ Selection: ${val}`,
7200
7560
  ));
7201
7561
  }
7202
7562
  };
7203
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%", flexGrow: 1 }, windowedHistory.items.map((msg, idx) => /* @__PURE__ */ React10.createElement(MessageItem, { key: msg.id || idx, msg, showFullThinking, columns: stdout?.columns || 80 }))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", padding: 1, width: "100%" }, (activeView === "chat" || ["ask", "approval", "terminalApproval"].includes(activeView)) && /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React10.createElement(
7563
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", width: "100%", flexGrow: 1 }, windowedHistory.items.map((msg, idx) => /* @__PURE__ */ React11.createElement(MessageItem, { key: msg.id || idx, msg, showFullThinking, columns: stdout?.columns || 80 }))), /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", padding: 1, width: "100%" }, (activeView === "chat" || ["ask", "approval", "terminalApproval"].includes(activeView)) && /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", width: "100%" }, /* @__PURE__ */ React11.createElement(
7204
7564
  ChatLayout_default,
7205
7565
  {
7206
7566
  messages: messages.slice(completedIndex),
7207
7567
  showFullThinking,
7208
7568
  columns: Math.max(20, (stdout?.columns || 80) - 1)
7209
7569
  }
7210
- ), activeCommand && /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused }))), isInitializing ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "round", borderColor: "gray", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "yellow", bold: true }, "\u{1F511}", emojiSpace(2), "API KEY REQUIRED")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, null, "Please enter your Gemini API Key to initialize the agent."), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React10.createElement(
7570
+ ), activeCommand && /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(TerminalBox, { command: activeCommand, output: execOutput, isFocused: isTerminalFocused }))), isInitializing ? /* @__PURE__ */ React11.createElement(Box11, { borderStyle: "double", borderColor: "magenta", padding: 1, flexShrink: 0 }, /* @__PURE__ */ React11.createElement(Text11, { color: "magenta" }, "\u{1F30A} Starting Flux Flow...")) : !apiKey ? /* @__PURE__ */ React11.createElement(Box11, { borderStyle: "round", borderColor: "gray", padding: 0, flexDirection: "column", flexShrink: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "yellow", bold: true }, "\u{1F511}", emojiSpace(2), "API KEY REQUIRED")), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text11, null, "Please enter your Gemini API Key to initialize the agent."), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, "\u{1F4A0} "), /* @__PURE__ */ React11.createElement(
7211
7571
  TextInput3,
7212
7572
  {
7213
7573
  value: tempKey,
@@ -7215,7 +7575,7 @@ Selection: ${val}`,
7215
7575
  onSubmit: handleSetup,
7216
7576
  mask: "*"
7217
7577
  }
7218
- ))), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm and initialize)"))) : renderActiveView(), confirmExit && /* @__PURE__ */ React10.createElement(Box10, { borderStyle: "round", borderColor: "red", paddingX: 2, marginY: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "\u{1F534} EXIT CONFIRMATION: "), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, "Press "), /* @__PURE__ */ React10.createElement(Text10, { color: "red", bold: true }, "CTRL + C"), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " again to exit (", exitCountdown, "s). Press "), /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "ESC"), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, " to cancel.")), /* @__PURE__ */ React10.createElement(Box10, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(
7578
+ ))), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm and initialize)"))) : renderActiveView(), confirmExit && /* @__PURE__ */ React11.createElement(Box11, { borderStyle: "round", borderColor: "red", paddingX: 2, marginY: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true }, "\u{1F534} EXIT CONFIRMATION: "), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, "Press "), /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true }, "CTRL + C"), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " again to exit (", exitCountdown, "s). Press "), /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, "ESC"), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, " to cancel.")), /* @__PURE__ */ React11.createElement(Box11, { flexShrink: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(
7219
7579
  StatusBar_default,
7220
7580
  {
7221
7581
  mode,
@@ -7232,14 +7592,14 @@ Selection: ${val}`,
7232
7592
  const agentActiveMs = sessionApiTime + sessionToolTime;
7233
7593
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
7234
7594
  const toolPercent = agentActiveMs > 0 ? (sessionToolTime / agentActiveMs * 100).toFixed(1) : "0.0";
7235
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { marginBottom: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React10.createElement(Text10, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column" }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, chatId)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React10.createElement(Text10, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React10.createElement(Text10, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, successRate, "%")), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1 }, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React10.createElement(Box10, null, /* @__PURE__ */ React10.createElement(Box10, { width: 20 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React10.createElement(Box10, { marginLeft: 2 }, /* @__PURE__ */ React10.createElement(Box10, { width: 18 }, /* @__PURE__ */ React10.createElement(Text10, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React10.createElement(Text10, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
7595
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", paddingX: 3, paddingY: 1, borderColor: "red", width: Math.min(100, (stdout?.columns || 100) - 2), marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box11, { marginBottom: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "cyan", bold: true }, "Agent powering down. ", /* @__PURE__ */ React11.createElement(Text11, { color: "magenta" }, "Goodbye!"))), /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column" }, /* @__PURE__ */ React11.createElement(Text11, { color: "white", bold: true, underline: true }, "Interaction Summary"), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Session ID:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, chatId)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tool Calls:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionToolSuccess + sessionToolFailure + sessionToolDenied, " ( ", /* @__PURE__ */ React11.createElement(Text11, { color: "green" }, "\u2713 ", sessionToolSuccess), " ", /* @__PURE__ */ React11.createElement(Text11, { color: "yellow" }, "\u2298 ", sessionToolDenied), " ", /* @__PURE__ */ React11.createElement(Text11, { color: "red" }, "\u2715 ", sessionToolFailure), " )")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Success Rate:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, successRate, "%")), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Tokens Consumed:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatTokens(sessionTotalTokens))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Images Made:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, sessionImageCount || 0)), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Image Credits:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, Number(((sessionImageCredits || 0) * 1e3).toFixed(0)), " credits"))), /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "white", bold: true, underline: true }, "Performance"), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Wall Time:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(wallTimeMs))), /* @__PURE__ */ React11.createElement(Box11, null, /* @__PURE__ */ React11.createElement(Box11, { width: 20 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue" }, "Agent Active:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(agentActiveMs))), /* @__PURE__ */ React11.createElement(Box11, { marginLeft: 2 }, /* @__PURE__ */ React11.createElement(Box11, { width: 18 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue", dimColor: true }, "\xBB API Time:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(sessionApiTime), " (", apiPercent, "%)")), /* @__PURE__ */ React11.createElement(Box11, { marginLeft: 2 }, /* @__PURE__ */ React11.createElement(Box11, { width: 18 }, /* @__PURE__ */ React11.createElement(Text11, { color: "blue", dimColor: true }, "\xBB Tool Time:")), /* @__PURE__ */ React11.createElement(Text11, { color: "white" }, formatMsDuration(sessionToolTime), " (", toolPercent, "%)"))));
7236
7596
  })(), suggestions.length > 0 && (() => {
7237
7597
  const windowSize = 5;
7238
7598
  const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
7239
7599
  const visible = suggestions.slice(startIdx, startIdx + windowSize);
7240
7600
  const remaining = suggestions.length - (startIdx + visible.length);
7241
- return /* @__PURE__ */ React10.createElement(
7242
- Box10,
7601
+ return /* @__PURE__ */ React11.createElement(
7602
+ Box11,
7243
7603
  {
7244
7604
  flexDirection: "column",
7245
7605
  borderStyle: "round",
@@ -7248,22 +7608,22 @@ Selection: ${val}`,
7248
7608
  paddingY: 0,
7249
7609
  width: "100%"
7250
7610
  },
7251
- /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true, dimColor: true }, "\u{1F50D} COMMAND SUGGESTIONS")),
7611
+ /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", bold: true, dimColor: true }, "\u{1F50D} COMMAND SUGGESTIONS")),
7252
7612
  visible.map((s, i) => {
7253
7613
  const actualIdx = startIdx + i;
7254
7614
  const isActive = actualIdx === selectedIndex;
7255
7615
  const isGemmaDisabled = s.cmd === "gemma-4-31b-it" && apiTier !== "Free";
7256
- return /* @__PURE__ */ React10.createElement(
7257
- Box10,
7616
+ return /* @__PURE__ */ React11.createElement(
7617
+ Box11,
7258
7618
  {
7259
7619
  key: s.cmd,
7260
7620
  flexDirection: "row",
7261
7621
  backgroundColor: isActive ? "#2a2a2a" : void 0,
7262
7622
  paddingX: 1
7263
7623
  },
7264
- /* @__PURE__ */ React10.createElement(Box10, { width: 3 }, /* @__PURE__ */ React10.createElement(Text10, { color: isActive ? "cyan" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
7265
- /* @__PURE__ */ React10.createElement(Box10, { width: 32 }, /* @__PURE__ */ React10.createElement(
7266
- Text10,
7624
+ /* @__PURE__ */ React11.createElement(Box11, { width: 3 }, /* @__PURE__ */ React11.createElement(Text11, { color: isActive ? "cyan" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
7625
+ /* @__PURE__ */ React11.createElement(Box11, { width: 32 }, /* @__PURE__ */ React11.createElement(
7626
+ Text11,
7267
7627
  {
7268
7628
  color: isGemmaDisabled ? "gray" : isActive ? "yellow" : "white",
7269
7629
  bold: isActive,
@@ -7271,10 +7631,10 @@ Selection: ${val}`,
7271
7631
  },
7272
7632
  s.cmd
7273
7633
  )),
7274
- /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", italic: true, dimColor: !isActive }, s.desc))
7634
+ /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", italic: true, dimColor: !isActive }, s.desc))
7275
7635
  );
7276
7636
  }),
7277
- suggestions.length > 5 && /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, height: 1 }, remaining > 0 ? /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, " ... (", remaining, " more commands available)") : /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, " (End of list)"))
7637
+ suggestions.length > 5 && /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, height: 1 }, remaining > 0 ? /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, " ... (", remaining, " more commands available)") : /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, " (End of list)"))
7278
7638
  );
7279
7639
  })()));
7280
7640
  }
@@ -7293,6 +7653,8 @@ var init_app = __esm({
7293
7653
  init_ResumeModal();
7294
7654
  init_MemoryModal();
7295
7655
  init_UpdateProcessor();
7656
+ init_revert();
7657
+ init_RevertModal();
7296
7658
  init_usage();
7297
7659
  init_TerminalBox();
7298
7660
  init_arg_parser();
@@ -7303,11 +7665,11 @@ var init_app = __esm({
7303
7665
  init_text();
7304
7666
  SESSION_START_TIME = Date.now();
7305
7667
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog.html";
7306
- packageJsonPath = path15.join(path15.dirname(fileURLToPath(import.meta.url)), "../package.json");
7307
- packageJson = JSON.parse(fs17.readFileSync(packageJsonPath, "utf8"));
7668
+ packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
7669
+ packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
7308
7670
  versionFluxflow = packageJson.version;
7309
7671
  updatedOn = packageJson.date || "2026-05-20";
7310
- ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React10.createElement(Text10, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React10.createElement(Box10, { marginTop: 0 }, /* @__PURE__ */ React10.createElement(
7672
+ ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "gray", padding: 0, width: "100%" }, /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "magenta", bold: true, underline: true }, "\u{1F7E3} STEERING HINT RESOLUTION")), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, null, "The agent already finished the task before your hint was consumed.")), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React11.createElement(Text11, { italic: true, color: "gray" }, '"', data, '"')), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "cyan" }, "How would you like to proceed?")), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 0 }, /* @__PURE__ */ React11.createElement(
7311
7673
  CommandMenu,
7312
7674
  {
7313
7675
  title: "Select Action",
@@ -7410,7 +7772,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
7410
7772
  ], { stdio: "inherit" });
7411
7773
  cp.on("exit", (code) => process.exit(code || 0));
7412
7774
  } else {
7413
- const { default: React11 } = await import("react");
7775
+ const { default: React12 } = await import("react");
7414
7776
  const { render } = await import("ink");
7415
7777
  const { default: App2 } = await Promise.resolve().then(() => (init_app(), app_exports));
7416
7778
  process.env.NODE_NO_WARNINGS = "1";
@@ -7433,5 +7795,5 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
7433
7795
  console.warn = (...args) => !isNoise(args) && originalWarn(...args);
7434
7796
  console.error = (...args) => !isNoise(args) && originalError(...args);
7435
7797
  process.stdout.write("\x1Bc");
7436
- render(/* @__PURE__ */ React11.createElement(App2, { args: process.argv.slice(2) }), { exitOnCtrlC: false });
7798
+ render(/* @__PURE__ */ React12.createElement(App2, { args: process.argv.slice(2) }), { exitOnCtrlC: false });
7437
7799
  }