fluxflow-cli 1.13.6 → 1.14.1

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 +1275 -916
  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
@@ -1129,7 +1134,7 @@ ${projectContextBlock}
1129
1134
  -- FORMATTING --
1130
1135
  - Clean, concise responses
1131
1136
  - Tables: GFM (Max 4 cols, short rows)
1132
- - NO LaTeX. Code blocks for literature.${mode === "Flux" ? "" : " Kaomojis"}
1137
+ - NO LaTeX. Code blocks for literature${mode === "Flux" ? "" : ". Kaomojis"}
1133
1138
 
1134
1139
  -- RESPONSE RULES --
1135
1140
  - End with [turn: continue] for more steps or [turn: finish] when done
@@ -1165,15 +1170,165 @@ 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) return;
1229
+ const ledger = readEncryptedJson(LEDGER_FILE, []);
1230
+ ledger.push(currentTransaction);
1231
+ if (ledger.length > 500) {
1232
+ const removed = ledger.shift();
1233
+ if (removed.changes) {
1234
+ for (const change of removed.changes) {
1235
+ if (change.backupFile) {
1236
+ const backupPath = path4.join(BACKUPS_DIR, removed.chatId, change.backupFile);
1237
+ await fs5.remove(backupPath);
1238
+ }
1239
+ }
1240
+ }
1241
+ }
1242
+ writeEncryptedJson(LEDGER_FILE, ledger);
1243
+ currentTransaction = null;
1244
+ },
1245
+ /**
1246
+ * Reverts the codebase to a state immediately before the target transaction.
1247
+ * Reverts the target transaction and all subsequent ones in reverse sequential order.
1248
+ * Returns the target prompt text so it can be loaded back into the user input.
1249
+ */
1250
+ async rollbackToBefore(txId) {
1251
+ const ledger = readEncryptedJson(LEDGER_FILE, null);
1252
+ if (!ledger) throw new Error("No transaction ledger found.");
1253
+ const targetIndex = ledger.findIndex((t) => t.id === txId);
1254
+ if (targetIndex === -1) throw new Error(`Transaction [${txId}] not found.`);
1255
+ const chatId = ledger[targetIndex].chatId;
1256
+ const targetPrompt = ledger[targetIndex].prompt;
1257
+ const toRevert = ledger.slice(targetIndex).filter((t) => t.chatId === chatId && !t.reverted).reverse();
1258
+ for (const tx of toRevert) {
1259
+ for (const change of [...tx.changes].reverse()) {
1260
+ if (change.type === "create") {
1261
+ if (await fs5.pathExists(change.filePath)) {
1262
+ await fs5.remove(change.filePath);
1263
+ }
1264
+ } else if (change.type === "update") {
1265
+ const backupPath = path4.join(BACKUPS_DIR, tx.chatId, change.backupFile);
1266
+ if (await fs5.pathExists(backupPath)) {
1267
+ const encrypted = await fs5.readFile(backupPath, "utf8");
1268
+ const decrypted = decryptAes(encrypted);
1269
+ await fs5.writeFile(change.filePath, decrypted, "utf8");
1270
+ }
1271
+ }
1272
+ }
1273
+ tx.reverted = true;
1274
+ }
1275
+ for (const tx of toRevert) {
1276
+ for (const change of tx.changes) {
1277
+ if (change.backupFile) {
1278
+ const backupPath = path4.join(BACKUPS_DIR, tx.chatId, change.backupFile);
1279
+ await fs5.remove(backupPath);
1280
+ }
1281
+ }
1282
+ }
1283
+ const updatedLedger = ledger.filter((t) => !toRevert.some((r) => r.id === t.id));
1284
+ writeEncryptedJson(LEDGER_FILE, updatedLedger);
1285
+ return {
1286
+ success: true,
1287
+ chatId,
1288
+ targetPrompt
1289
+ };
1290
+ },
1291
+ /**
1292
+ * Gets all non-reverted prompt transactions for a specific chat.
1293
+ */
1294
+ async getChatHistory(chatId) {
1295
+ try {
1296
+ const ledger = readEncryptedJson(LEDGER_FILE, []);
1297
+ return ledger.filter((t) => t.chatId === chatId && !t.reverted);
1298
+ } catch (e) {
1299
+ return [];
1300
+ }
1301
+ },
1302
+ /**
1303
+ * Cleans up all transaction logs and backups associated with a deleted chat.
1304
+ */
1305
+ async deleteChatBackups(chatId) {
1306
+ try {
1307
+ const chatBackupDir = path4.join(BACKUPS_DIR, chatId);
1308
+ await fs5.remove(chatBackupDir);
1309
+ let ledger = readEncryptedJson(LEDGER_FILE, []);
1310
+ const originalLength = ledger.length;
1311
+ ledger = ledger.filter((t) => t.chatId !== chatId);
1312
+ if (ledger.length !== originalLength) {
1313
+ writeEncryptedJson(LEDGER_FILE, ledger);
1314
+ }
1315
+ } catch (e) {
1316
+ }
1317
+ }
1318
+ };
1319
+ }
1320
+ });
1321
+
1322
+ // src/utils/history.js
1323
+ import fs6 from "fs-extra";
1324
+ import path5 from "path";
1171
1325
  import { nanoid } from "nanoid";
1172
1326
  var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, parseCustomDate, cleanupLogFile, cleanupOldLogs, getTruncatedHistory;
1173
1327
  var init_history = __esm({
1174
1328
  "src/utils/history.js"() {
1175
1329
  init_crypto();
1176
1330
  init_paths();
1331
+ init_revert();
1177
1332
  WRITE_LOCK = Promise.resolve();
1178
1333
  withLock = (op) => {
1179
1334
  const nextLock = WRITE_LOCK.then(async () => {
@@ -1189,7 +1344,7 @@ var init_history = __esm({
1189
1344
  return nextLock;
1190
1345
  };
1191
1346
  loadHistory = async () => {
1192
- if (await fs5.pathExists(HISTORY_FILE)) {
1347
+ if (await fs6.pathExists(HISTORY_FILE)) {
1193
1348
  try {
1194
1349
  return readEncryptedJson(HISTORY_FILE, {});
1195
1350
  } catch (e) {
@@ -1239,6 +1394,7 @@ var init_history = __esm({
1239
1394
  delete cache[id];
1240
1395
  writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
1241
1396
  }
1397
+ await RevertManager.deleteChatBackups(id);
1242
1398
  return history;
1243
1399
  });
1244
1400
  };
@@ -1308,8 +1464,8 @@ var init_history = __esm({
1308
1464
  };
1309
1465
  cleanupLogFile = async (filePath) => {
1310
1466
  try {
1311
- if (!await fs5.pathExists(filePath)) return;
1312
- const content = await fs5.readFile(filePath, "utf8");
1467
+ if (!await fs6.pathExists(filePath)) return;
1468
+ const content = await fs6.readFile(filePath, "utf8");
1313
1469
  if (!content.trim()) return;
1314
1470
  const lines = content.split("\n");
1315
1471
  const entries = [];
@@ -1349,26 +1505,26 @@ var init_history = __esm({
1349
1505
  }
1350
1506
  const finalContent = keptEntries.join("\n").trim();
1351
1507
  if (finalContent) {
1352
- await fs5.writeFile(filePath, finalContent + "\n", "utf8");
1508
+ await fs6.writeFile(filePath, finalContent + "\n", "utf8");
1353
1509
  } else {
1354
- await fs5.writeFile(filePath, "", "utf8");
1510
+ await fs6.writeFile(filePath, "", "utf8");
1355
1511
  }
1356
1512
  } catch (e) {
1357
1513
  }
1358
1514
  };
1359
1515
  cleanupOldLogs = async (logsDir) => {
1360
1516
  try {
1361
- if (!await fs5.pathExists(logsDir)) return;
1517
+ if (!await fs6.pathExists(logsDir)) return;
1362
1518
  const cleanRecursive = async (dir) => {
1363
- const files = await fs5.readdir(dir);
1519
+ const files = await fs6.readdir(dir);
1364
1520
  for (const file of files) {
1365
- const fullPath = path4.join(dir, file);
1366
- const stat = await fs5.stat(fullPath);
1521
+ const fullPath = path5.join(dir, file);
1522
+ const stat = await fs6.stat(fullPath);
1367
1523
  if (stat.isDirectory()) {
1368
1524
  await cleanRecursive(fullPath);
1369
- const subFiles = await fs5.readdir(fullPath);
1525
+ const subFiles = await fs6.readdir(fullPath);
1370
1526
  if (subFiles.length === 0) {
1371
- await fs5.remove(fullPath);
1527
+ await fs6.remove(fullPath);
1372
1528
  }
1373
1529
  } else if (file.endsWith(".log")) {
1374
1530
  await cleanupLogFile(fullPath);
@@ -1391,8 +1547,8 @@ var init_history = __esm({
1391
1547
  });
1392
1548
 
1393
1549
  // src/utils/usage.js
1394
- import fs6 from "fs-extra";
1395
- import path5 from "path";
1550
+ import fs7 from "fs-extra";
1551
+ import path6 from "path";
1396
1552
  import os3 from "os";
1397
1553
  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
1554
  var init_usage = __esm({
@@ -1401,14 +1557,14 @@ var init_usage = __esm({
1401
1557
  init_crypto();
1402
1558
  getLocalBackupPath = () => {
1403
1559
  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");
1560
+ const localAppData = process.env.LOCALAPPDATA || path6.join(os3.homedir(), "AppData", "Local");
1561
+ return path6.join(localAppData, "FxFl", "backups", "backup.json");
1406
1562
  }
1407
1563
  if (process.platform === "darwin") {
1408
- return path5.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
1564
+ return path6.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
1409
1565
  }
1410
- const xdgDataHome = process.env.XDG_DATA_HOME || path5.join(os3.homedir(), ".local", "share");
1411
- return path5.join(xdgDataHome, "fxfl", "backups", "backup.json");
1566
+ const xdgDataHome = process.env.XDG_DATA_HOME || path6.join(os3.homedir(), ".local", "share");
1567
+ return path6.join(xdgDataHome, "fxfl", "backups", "backup.json");
1412
1568
  };
1413
1569
  BACKUP_FILE = getLocalBackupPath();
1414
1570
  generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
@@ -1433,8 +1589,8 @@ var init_usage = __esm({
1433
1589
  let primaryData = null;
1434
1590
  let backupData = null;
1435
1591
  try {
1436
- if (await fs6.exists(tempFile)) {
1437
- const rawContent = (await fs6.readFile(tempFile, "utf8")).trim();
1592
+ if (await fs7.exists(tempFile)) {
1593
+ const rawContent = (await fs7.readFile(tempFile, "utf8")).trim();
1438
1594
  let parsed = null;
1439
1595
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1440
1596
  parsed = JSON.parse(rawContent);
@@ -1444,26 +1600,26 @@ var init_usage = __esm({
1444
1600
  if (parsed && parsed.date && parsed.stats) {
1445
1601
  primaryData = parsed;
1446
1602
  try {
1447
- await fs6.rename(tempFile, USAGE_FILE);
1603
+ await fs7.rename(tempFile, USAGE_FILE);
1448
1604
  } catch (e) {
1449
1605
  }
1450
1606
  } else {
1451
1607
  try {
1452
- await fs6.remove(tempFile);
1608
+ await fs7.remove(tempFile);
1453
1609
  } catch (e) {
1454
1610
  }
1455
1611
  }
1456
1612
  }
1457
1613
  } catch (err) {
1458
1614
  try {
1459
- await fs6.remove(tempFile);
1615
+ await fs7.remove(tempFile);
1460
1616
  } catch (e) {
1461
1617
  }
1462
1618
  }
1463
1619
  if (!primaryData) {
1464
1620
  try {
1465
- if (await fs6.exists(USAGE_FILE)) {
1466
- const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1621
+ if (await fs7.exists(USAGE_FILE)) {
1622
+ const rawContent = (await fs7.readFile(USAGE_FILE, "utf8")).trim();
1467
1623
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1468
1624
  primaryData = JSON.parse(rawContent);
1469
1625
  } else {
@@ -1474,8 +1630,8 @@ var init_usage = __esm({
1474
1630
  }
1475
1631
  }
1476
1632
  try {
1477
- if (await fs6.exists(BACKUP_FILE)) {
1478
- const rawContent = (await fs6.readFile(BACKUP_FILE, "utf8")).trim();
1633
+ if (await fs7.exists(BACKUP_FILE)) {
1634
+ const rawContent = (await fs7.readFile(BACKUP_FILE, "utf8")).trim();
1479
1635
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1480
1636
  backupData = JSON.parse(rawContent);
1481
1637
  } else {
@@ -1489,8 +1645,8 @@ var init_usage = __esm({
1489
1645
  if (primaryData.saveId !== backupData.saveId) {
1490
1646
  resolvedData = primaryData;
1491
1647
  try {
1492
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1493
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1648
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1649
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1494
1650
  } catch (e) {
1495
1651
  }
1496
1652
  } else {
@@ -1499,15 +1655,15 @@ var init_usage = __esm({
1499
1655
  } else if (primaryData && !backupData) {
1500
1656
  resolvedData = primaryData;
1501
1657
  try {
1502
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1503
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1658
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1659
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1504
1660
  } catch (e) {
1505
1661
  }
1506
1662
  } else if (!primaryData && backupData) {
1507
1663
  resolvedData = backupData;
1508
1664
  try {
1509
- await fs6.ensureDir(path5.dirname(USAGE_FILE));
1510
- await fs6.copy(BACKUP_FILE, USAGE_FILE);
1665
+ await fs7.ensureDir(path6.dirname(USAGE_FILE));
1666
+ await fs7.copy(BACKUP_FILE, USAGE_FILE);
1511
1667
  } catch (e) {
1512
1668
  }
1513
1669
  }
@@ -1526,11 +1682,11 @@ var init_usage = __esm({
1526
1682
  flushUsage = async () => {
1527
1683
  if (!isDirty || !cachedUsage) return;
1528
1684
  try {
1529
- await fs6.ensureDir(path5.dirname(USAGE_FILE));
1685
+ await fs7.ensureDir(path6.dirname(USAGE_FILE));
1530
1686
  let diskData = null;
1531
1687
  try {
1532
- if (await fs6.exists(USAGE_FILE)) {
1533
- const rawContent = (await fs6.readFile(USAGE_FILE, "utf8")).trim();
1688
+ if (await fs7.exists(USAGE_FILE)) {
1689
+ const rawContent = (await fs7.readFile(USAGE_FILE, "utf8")).trim();
1534
1690
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
1535
1691
  diskData = JSON.parse(rawContent);
1536
1692
  } else {
@@ -1561,14 +1717,14 @@ var init_usage = __esm({
1561
1717
  cachedUsage.saveId = generateSaveId();
1562
1718
  const tempFile = USAGE_FILE + ".tmp";
1563
1719
  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);
1720
+ await fs7.writeFile(tempFile, encryptedStr, "utf8");
1721
+ const fd = await fs7.open(tempFile, "r+");
1722
+ await fs7.fsync(fd);
1723
+ await fs7.close(fd);
1724
+ await fs7.rename(tempFile, USAGE_FILE);
1569
1725
  try {
1570
- await fs6.ensureDir(path5.dirname(BACKUP_FILE));
1571
- await fs6.copy(USAGE_FILE, BACKUP_FILE);
1726
+ await fs7.ensureDir(path6.dirname(BACKUP_FILE));
1727
+ await fs7.copy(USAGE_FILE, BACKUP_FILE);
1572
1728
  } catch (backupErr) {
1573
1729
  }
1574
1730
  isDirty = false;
@@ -2221,8 +2377,8 @@ var init_chat = __esm({
2221
2377
  });
2222
2378
 
2223
2379
  // src/tools/view_file.js
2224
- import fs7 from "fs";
2225
- import path6 from "path";
2380
+ import fs8 from "fs";
2381
+ import path7 from "path";
2226
2382
  var view_file;
2227
2383
  var init_view_file = __esm({
2228
2384
  "src/tools/view_file.js"() {
@@ -2234,16 +2390,16 @@ var init_view_file = __esm({
2234
2390
  const finalStart = sLine || 1;
2235
2391
  const finalEnd = eLine || (sLine ? sLine + 800 : 800);
2236
2392
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
2237
- const absolutePath = path6.resolve(process.cwd(), targetPath);
2393
+ const absolutePath = path7.resolve(process.cwd(), targetPath);
2238
2394
  try {
2239
- if (!fs7.existsSync(absolutePath)) {
2395
+ if (!fs8.existsSync(absolutePath)) {
2240
2396
  return `ERROR: File [${targetPath}] does not exist.`;
2241
2397
  }
2242
- const stats = fs7.statSync(absolutePath);
2398
+ const stats = fs8.statSync(absolutePath);
2243
2399
  if (stats.isDirectory()) {
2244
2400
  return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
2245
2401
  }
2246
- const ext = path6.extname(targetPath).toLowerCase();
2402
+ const ext = path7.extname(targetPath).toLowerCase();
2247
2403
  const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
2248
2404
  if (videoExtensions.includes(ext)) {
2249
2405
  const format = ext.slice(1).toUpperCase();
@@ -2259,7 +2415,7 @@ var init_view_file = __esm({
2259
2415
  ".doc": "application/msword"
2260
2416
  };
2261
2417
  if (mimeMap[ext]) {
2262
- const buffer = fs7.readFileSync(absolutePath);
2418
+ const buffer = fs8.readFileSync(absolutePath);
2263
2419
  const base64 = buffer.toString("base64");
2264
2420
  const mimeType = mimeMap[ext];
2265
2421
  return {
@@ -2272,7 +2428,7 @@ var init_view_file = __esm({
2272
2428
  }
2273
2429
  };
2274
2430
  }
2275
- let content = fs7.readFileSync(absolutePath, "utf8");
2431
+ let content = fs8.readFileSync(absolutePath, "utf8");
2276
2432
  if (content.startsWith("\uFEFF")) {
2277
2433
  content = content.slice(1);
2278
2434
  }
@@ -2295,24 +2451,26 @@ ${code}`;
2295
2451
  });
2296
2452
 
2297
2453
  // src/tools/write_file.js
2298
- import fs8 from "fs";
2299
- import path7 from "path";
2454
+ import fs9 from "fs";
2455
+ import path8 from "path";
2300
2456
  var write_file;
2301
2457
  var init_write_file = __esm({
2302
2458
  "src/tools/write_file.js"() {
2303
2459
  init_arg_parser();
2460
+ init_revert();
2304
2461
  write_file = async (args) => {
2305
2462
  let { path: targetPath, content } = parseArgs(args);
2306
2463
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
2307
2464
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
2308
2465
  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);
2466
+ const absolutePath = path8.resolve(process.cwd(), targetPath);
2467
+ const parentDir = path8.dirname(absolutePath);
2311
2468
  try {
2469
+ await RevertManager.recordFileChange(absolutePath);
2312
2470
  let ancestry = "";
2313
- if (fs8.existsSync(absolutePath)) {
2471
+ if (fs9.existsSync(absolutePath)) {
2314
2472
  try {
2315
- const oldData = fs8.readFileSync(absolutePath, "utf8");
2473
+ const oldData = fs9.readFileSync(absolutePath, "utf8");
2316
2474
  const lines = oldData.split(/\r?\n/);
2317
2475
  ancestry = `Old File contents:
2318
2476
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
@@ -2324,15 +2482,15 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
2324
2482
  `;
2325
2483
  }
2326
2484
  }
2327
- if (!fs8.existsSync(parentDir)) {
2328
- fs8.mkdirSync(parentDir, { recursive: true });
2485
+ if (!fs9.existsSync(parentDir)) {
2486
+ fs9.mkdirSync(parentDir, { recursive: true });
2329
2487
  }
2330
2488
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2331
2489
  const processedContent = strip(content);
2332
2490
  const lineCount = processedContent.split(/\r?\n/).length;
2333
2491
  const originalSize = Buffer.byteLength(processedContent, "utf8");
2334
- fs8.writeFileSync(absolutePath, processedContent, "utf8");
2335
- let verifiedContent = fs8.readFileSync(absolutePath, "utf8");
2492
+ fs9.writeFileSync(absolutePath, processedContent, "utf8");
2493
+ let verifiedContent = fs9.readFileSync(absolutePath, "utf8");
2336
2494
  const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
2337
2495
  const verifiedLines = verifiedContent.split(/\r?\n/);
2338
2496
  const verifiedLineCount = verifiedLines.length;
@@ -2368,32 +2526,37 @@ Check if Starting and Ending matches your write.`;
2368
2526
  });
2369
2527
 
2370
2528
  // src/tools/update_file.js
2371
- import fs9 from "fs";
2372
- import path8 from "path";
2529
+ import fs10 from "fs";
2530
+ import path9 from "path";
2373
2531
  var update_file;
2374
2532
  var init_update_file = __esm({
2375
2533
  "src/tools/update_file.js"() {
2376
2534
  init_arg_parser();
2535
+ init_revert();
2377
2536
  update_file = async (args) => {
2378
- let { path: targetPath, content_to_replace, content_to_add } = parseArgs(args);
2537
+ const parsed = parseArgs(args);
2538
+ const targetPath = parsed.path;
2539
+ let content_to_replace = parsed.content_to_replace !== void 0 ? parsed.content_to_replace : parsed.replaceContent;
2540
+ let content_to_add = parsed.content_to_add !== void 0 ? parsed.content_to_add : parsed.newContent;
2379
2541
  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.';
2542
+ if (content_to_replace === void 0) return 'ERROR: Missing "replaceContent" argument.';
2543
+ if (content_to_add === void 0) return 'ERROR: Missing "newContent" argument.';
2382
2544
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2383
2545
  content_to_replace = strip(content_to_replace);
2384
2546
  content_to_add = strip(content_to_add);
2385
- const absolutePath = path8.resolve(process.cwd(), targetPath);
2547
+ const absolutePath = path9.resolve(process.cwd(), targetPath);
2386
2548
  try {
2387
- if (!fs9.existsSync(absolutePath)) {
2549
+ if (!fs10.existsSync(absolutePath)) {
2388
2550
  return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
2389
2551
  }
2390
- let diskContent = fs9.readFileSync(absolutePath, "utf8");
2552
+ await RevertManager.recordFileChange(absolutePath);
2553
+ let diskContent = fs10.readFileSync(absolutePath, "utf8");
2391
2554
  if (diskContent.startsWith("\uFEFF")) {
2392
2555
  diskContent = diskContent.slice(1);
2393
2556
  }
2394
2557
  const normalizedDisk = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
2395
2558
  if (diskContent !== normalizedDisk) {
2396
- fs9.writeFileSync(absolutePath, normalizedDisk, "utf8");
2559
+ fs10.writeFileSync(absolutePath, normalizedDisk, "utf8");
2397
2560
  diskContent = normalizedDisk;
2398
2561
  }
2399
2562
  const currentContent = diskContent;
@@ -2462,7 +2625,7 @@ var init_update_file = __esm({
2462
2625
  const firstLeadingContext = currentContent.substring(firstLineStart, startPos);
2463
2626
  const finalContentToAdd = adjustIndentation(content_to_add, firstMatchContent, firstLeadingContext);
2464
2627
  const finalContentToReplace = firstMatchContent;
2465
- fs9.writeFileSync(absolutePath, newFileContent, "utf8");
2628
+ fs10.writeFileSync(absolutePath, newFileContent, "utf8");
2466
2629
  const allOriginalLines = currentContent.split(/\r?\n/);
2467
2630
  const startLine = currentContent.substring(0, startPos).split(/\r?\n/).length;
2468
2631
  const oldLines = content_to_replace.split(/\r?\n/);
@@ -2725,34 +2888,34 @@ ${finalOutput}`);
2725
2888
  });
2726
2889
 
2727
2890
  // src/tools/read_folder.js
2728
- import fs10 from "fs";
2729
- import path9 from "path";
2891
+ import fs11 from "fs";
2892
+ import path10 from "path";
2730
2893
  var read_folder;
2731
2894
  var init_read_folder = __esm({
2732
2895
  "src/tools/read_folder.js"() {
2733
2896
  init_arg_parser();
2734
2897
  read_folder = async (args) => {
2735
2898
  const { path: targetPath = "." } = parseArgs(args);
2736
- const absolutePath = path9.resolve(process.cwd(), targetPath);
2899
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
2737
2900
  try {
2738
- if (!fs10.existsSync(absolutePath)) {
2901
+ if (!fs11.existsSync(absolutePath)) {
2739
2902
  return `ERROR: Path [${targetPath}] does not exist.`;
2740
2903
  }
2741
- const stats = fs10.statSync(absolutePath);
2904
+ const stats = fs11.statSync(absolutePath);
2742
2905
  if (!stats.isDirectory()) {
2743
2906
  return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
2744
2907
  }
2745
- const files = fs10.readdirSync(absolutePath);
2908
+ const files = fs11.readdirSync(absolutePath);
2746
2909
  const totalItems = files.length;
2747
2910
  const maxDisplay = 100;
2748
2911
  const displayItems = files.slice(0, maxDisplay);
2749
2912
  const folderData = [];
2750
2913
  for (const file of displayItems) {
2751
- const fPath = path9.join(absolutePath, file);
2914
+ const fPath = path10.join(absolutePath, file);
2752
2915
  let indicator = "\u{1F4C4}";
2753
2916
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
2754
2917
  try {
2755
- const fStats = fs10.statSync(fPath);
2918
+ const fStats = fs11.statSync(fPath);
2756
2919
  info = {
2757
2920
  name: file,
2758
2921
  type: fStats.isDirectory() ? "directory" : "file",
@@ -2835,13 +2998,14 @@ var init_ask_user = __esm({
2835
2998
 
2836
2999
  // src/tools/write_pdf.js
2837
3000
  import puppeteer3 from "puppeteer";
2838
- import path10 from "path";
2839
- import fs11 from "fs-extra";
3001
+ import path11 from "path";
3002
+ import fs12 from "fs-extra";
2840
3003
  import { PDFDocument } from "pdf-lib";
2841
3004
  var write_pdf;
2842
3005
  var init_write_pdf = __esm({
2843
3006
  "src/tools/write_pdf.js"() {
2844
3007
  init_arg_parser();
3008
+ init_revert();
2845
3009
  write_pdf = async (args) => {
2846
3010
  const {
2847
3011
  path: targetPath,
@@ -2851,10 +3015,11 @@ var init_write_pdf = __esm({
2851
3015
  } = parseArgs(args);
2852
3016
  if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
2853
3017
  if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
2854
- const absolutePath = path10.resolve(process.cwd(), targetPath);
3018
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
2855
3019
  let browser = null;
2856
3020
  try {
2857
- await fs11.ensureDir(path10.dirname(absolutePath));
3021
+ await fs12.ensureDir(path11.dirname(absolutePath));
3022
+ await RevertManager.recordFileChange(absolutePath);
2858
3023
  browser = await puppeteer3.launch({
2859
3024
  headless: true,
2860
3025
  args: [
@@ -2872,11 +3037,11 @@ var init_write_pdf = __esm({
2872
3037
  return null;
2873
3038
  }
2874
3039
  try {
2875
- const imgPath = path10.resolve(process.cwd(), originalSrc);
2876
- if (await fs11.pathExists(imgPath)) {
2877
- const ext = path10.extname(imgPath).toLowerCase().replace(".", "") || "png";
3040
+ const imgPath = path11.resolve(process.cwd(), originalSrc);
3041
+ if (await fs12.pathExists(imgPath)) {
3042
+ const ext = path11.extname(imgPath).toLowerCase().replace(".", "") || "png";
2878
3043
  const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
2879
- const base64 = await fs11.readFile(imgPath, "base64");
3044
+ const base64 = await fs12.readFile(imgPath, "base64");
2880
3045
  return `data:image/${mime};base64,${base64}`;
2881
3046
  }
2882
3047
  } catch (e) {
@@ -2891,9 +3056,9 @@ var init_write_pdf = __esm({
2891
3056
  const fullTag = match[0];
2892
3057
  if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
2893
3058
  try {
2894
- const cssPath = path10.resolve(process.cwd(), originalHref);
2895
- if (await fs11.pathExists(cssPath)) {
2896
- const cssContent = await fs11.readFile(cssPath, "utf-8");
3059
+ const cssPath = path11.resolve(process.cwd(), originalHref);
3060
+ if (await fs12.pathExists(cssPath)) {
3061
+ const cssContent = await fs12.readFile(cssPath, "utf-8");
2897
3062
  cssCache[fullTag] = `<style>${cssContent}</style>`;
2898
3063
  }
2899
3064
  } catch (e) {
@@ -2974,7 +3139,7 @@ var init_write_pdf = __esm({
2974
3139
  printBackground: true
2975
3140
  });
2976
3141
  const pdfDoc = await PDFDocument.load(pdfBytes);
2977
- const fileName = path10.basename(targetPath);
3142
+ const fileName = path11.basename(targetPath);
2978
3143
  pdfDoc.setTitle(`FluxFlow_${fileName}`);
2979
3144
  pdfDoc.setAuthor("FluxFlow CLI");
2980
3145
  pdfDoc.setSubject("Generated with Agentic AI System");
@@ -2982,8 +3147,8 @@ var init_write_pdf = __esm({
2982
3147
  pdfDoc.setCreator("FluxFlow PDF Engine");
2983
3148
  pdfDoc.setProducer("FluxFlow (Generative AI)");
2984
3149
  const finalPdfBytes = await pdfDoc.save();
2985
- await fs11.writeFile(absolutePath, finalPdfBytes);
2986
- const stats = await fs11.stat(absolutePath);
3150
+ await fs12.writeFile(absolutePath, finalPdfBytes);
3151
+ const stats = await fs12.stat(absolutePath);
2987
3152
  return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
2988
3153
  } catch (err) {
2989
3154
  return `ERROR: Failed to generate PDF [${targetPath}]: ${err.message}`;
@@ -2995,13 +3160,14 @@ var init_write_pdf = __esm({
2995
3160
  });
2996
3161
 
2997
3162
  // src/tools/write_docx.js
2998
- import fs12 from "fs-extra";
2999
- import path11 from "path";
3163
+ import fs13 from "fs-extra";
3164
+ import path12 from "path";
3000
3165
  import HTMLtoDOCX from "html-to-docx";
3001
3166
  var write_docx;
3002
3167
  var init_write_docx = __esm({
3003
3168
  "src/tools/write_docx.js"() {
3004
3169
  init_arg_parser();
3170
+ init_revert();
3005
3171
  write_docx = async (args) => {
3006
3172
  const {
3007
3173
  path: targetPath,
@@ -3009,10 +3175,11 @@ var init_write_docx = __esm({
3009
3175
  } = parseArgs(args);
3010
3176
  if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
3011
3177
  if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
3012
- const absolutePath = path11.resolve(process.cwd(), targetPath);
3178
+ const absolutePath = path12.resolve(process.cwd(), targetPath);
3013
3179
  try {
3014
- await fs12.ensureDir(path11.dirname(absolutePath));
3015
- const fileName = path11.basename(targetPath);
3180
+ await fs13.ensureDir(path12.dirname(absolutePath));
3181
+ await RevertManager.recordFileChange(absolutePath);
3182
+ const fileName = path12.basename(targetPath);
3016
3183
  const fullHtml = content.includes("<html") ? content : `
3017
3184
  <!DOCTYPE html>
3018
3185
  <html lang="en">
@@ -3033,7 +3200,7 @@ var init_write_docx = __esm({
3033
3200
  footer: true,
3034
3201
  pageNumber: true
3035
3202
  });
3036
- await fs12.writeFile(absolutePath, docxBuffer);
3203
+ await fs13.writeFile(absolutePath, docxBuffer);
3037
3204
  return `SUCCESS: Word document [${targetPath}] generated successfully.
3038
3205
  - Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
3039
3206
  } catch (err) {
@@ -3100,8 +3267,8 @@ var init_search_keyword = __esm({
3100
3267
  });
3101
3268
 
3102
3269
  // src/utils/settings.js
3103
- import fs13 from "fs-extra";
3104
- import path12 from "path";
3270
+ import fs14 from "fs-extra";
3271
+ import path13 from "path";
3105
3272
  var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
3106
3273
  var init_settings = __esm({
3107
3274
  "src/utils/settings.js"() {
@@ -3143,7 +3310,7 @@ var init_settings = __esm({
3143
3310
  loadSettings = async () => {
3144
3311
  let settingsObj = { ...DEFAULT_SETTINGS };
3145
3312
  try {
3146
- if (await fs13.exists(SETTINGS_FILE)) {
3313
+ if (await fs14.exists(SETTINGS_FILE)) {
3147
3314
  const saved = readAesEncryptedJson(SETTINGS_FILE);
3148
3315
  if (saved.imageSettings && saved.imageSettings.apiKey) {
3149
3316
  try {
@@ -3188,12 +3355,12 @@ var init_settings = __esm({
3188
3355
  const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
3189
3356
  const folders = ["logs", "secret"];
3190
3357
  for (const folder of folders) {
3191
- const src = path12.join(FLUXFLOW_DIR2, folder);
3192
- const dest = path12.join(newPath, folder);
3358
+ const src = path13.join(FLUXFLOW_DIR2, folder);
3359
+ const dest = path13.join(newPath, folder);
3193
3360
  try {
3194
- if (await fs13.exists(src)) {
3195
- await fs13.ensureDir(dest);
3196
- await fs13.copy(src, dest, { overwrite: true });
3361
+ if (await fs14.exists(src)) {
3362
+ await fs14.ensureDir(dest);
3363
+ await fs14.copy(src, dest, { overwrite: true });
3197
3364
  }
3198
3365
  } catch (err) {
3199
3366
  console.error(`Migration failed for ${folder}:`, err);
@@ -3219,7 +3386,7 @@ var init_settings = __esm({
3219
3386
  if (updated.imageSettings) {
3220
3387
  updated.imageSettings = { ...updated.imageSettings, apiKey: "" };
3221
3388
  }
3222
- await fs13.ensureDir(path12.dirname(SETTINGS_FILE));
3389
+ await fs14.ensureDir(path13.dirname(SETTINGS_FILE));
3223
3390
  writeAesEncryptedJson(SETTINGS_FILE, updated);
3224
3391
  return true;
3225
3392
  } catch (err) {
@@ -3239,8 +3406,8 @@ var init_fallback_key = __esm({
3239
3406
  });
3240
3407
 
3241
3408
  // src/tools/generate_image.js
3242
- import fs14 from "fs-extra";
3243
- import path13 from "path";
3409
+ import fs15 from "fs-extra";
3410
+ import path14 from "path";
3244
3411
  var injectPngMetadata, generate_image;
3245
3412
  var init_generate_image = __esm({
3246
3413
  "src/tools/generate_image.js"() {
@@ -3248,6 +3415,7 @@ var init_generate_image = __esm({
3248
3415
  init_settings();
3249
3416
  init_usage();
3250
3417
  init_fallback_key();
3418
+ init_revert();
3251
3419
  injectPngMetadata = (buffer, metadata = {}) => {
3252
3420
  try {
3253
3421
  if (buffer.length < 8 || buffer[0] !== 137 || buffer[1] !== 80 || buffer[2] !== 78 || buffer[3] !== 71) {
@@ -3419,9 +3587,10 @@ var init_generate_image = __esm({
3419
3587
  "Seed": String(seed)
3420
3588
  };
3421
3589
  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);
3590
+ const absolutePath = path14.resolve(process.cwd(), outputPath);
3591
+ await fs15.ensureDir(path14.dirname(absolutePath));
3592
+ await RevertManager.recordFileChange(absolutePath);
3593
+ await fs15.writeFile(absolutePath, finalBuffer);
3425
3594
  await recordImageGeneration(settings);
3426
3595
  return `SUCCESS: Image successfully generated from prompt [${prompt}] and saved to [${outputPath}].`;
3427
3596
  } catch (err) {
@@ -3590,8 +3759,8 @@ var init_tools = __esm({
3590
3759
 
3591
3760
  // src/utils/ai.js
3592
3761
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
3593
- import path14 from "path";
3594
- import fs15 from "fs";
3762
+ import path15 from "path";
3763
+ import fs16 from "fs";
3595
3764
  var client, TERMINATION_SIGNAL, signalTermination, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, detectToolCalls, initAI, consolidatePastMemories, getAIStream;
3596
3765
  var init_ai = __esm({
3597
3766
  "src/utils/ai.js"() {
@@ -3603,6 +3772,7 @@ var init_ai = __esm({
3603
3772
  init_arg_parser();
3604
3773
  init_terminal();
3605
3774
  init_paths();
3775
+ init_revert();
3606
3776
  client = null;
3607
3777
  TERMINATION_SIGNAL = false;
3608
3778
  signalTermination = () => {
@@ -3627,7 +3797,7 @@ var init_ai = __esm({
3627
3797
  try {
3628
3798
  const pArgs = parseArgs(argsStr);
3629
3799
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
3630
- return filePath ? path14.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3800
+ return filePath ? path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
3631
3801
  } catch (e) {
3632
3802
  return null;
3633
3803
  }
@@ -3754,16 +3924,15 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3754
3924
  }
3755
3925
  const toolContext = { chatId, sessionId: chatId, history };
3756
3926
  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`);
3927
+ if (toolName.toLowerCase() === "memory") {
3928
+ const isUserAction = janitorToolCall.args.includes("action='user'") || janitorToolCall.args.includes('action="user"');
3929
+ if (isUserAction && !result.startsWith("ERROR")) {
3930
+ if (onMemoryUpdated) onMemoryUpdated();
3931
+ if (process.stdout.isTTY) {
3932
+ process.stdout.write(`\x1B]0;Memory Updated\x07`);
3933
+ }
3934
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
3765
3935
  }
3766
- await new Promise((resolve) => setTimeout(resolve, 3e3));
3767
3936
  }
3768
3937
  }
3769
3938
  if (!scoreToolCalled) {
@@ -3795,9 +3964,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3795
3964
  process.stdout.write(`\x1B]0;Finalizing Error\x07`);
3796
3965
  }
3797
3966
  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)}
3967
+ const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3968
+ if (!fs16.existsSync(janitorErrDir)) fs16.mkdirSync(janitorErrDir, { recursive: true });
3969
+ fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${String(janitorErr)}
3801
3970
 
3802
3971
  `);
3803
3972
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -3806,8 +3975,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
3806
3975
  }
3807
3976
  }
3808
3977
  if (attempts) {
3809
- const janitorErrDir = path14.join(LOGS_DIR, "janitor");
3810
- fs15.appendFileSync(path14.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3978
+ const janitorErrDir = path15.join(LOGS_DIR, "janitor");
3979
+ fs16.appendFileSync(path15.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
3811
3980
 
3812
3981
 
3813
3982
  `);
@@ -4108,10 +4277,10 @@ ${newMemoryListStr}
4108
4277
  }
4109
4278
  }
4110
4279
  } 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"),
4280
+ const janitorLogDir = path15.join(LOGS_DIR, "janitor");
4281
+ if (!fs16.existsSync(janitorLogDir)) fs16.mkdirSync(janitorLogDir, { recursive: true });
4282
+ fs16.appendFileSync(
4283
+ path15.join(janitorLogDir, "error.log"),
4115
4284
  `[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${err.message}
4116
4285
  `
4117
4286
  );
@@ -4125,340 +4294,322 @@ ${newMemoryListStr}
4125
4294
  const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
4126
4295
  const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
4127
4296
  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..." };
4297
+ let agentText = originalText.replace(/\[TITLE-UPDATE\]/g, "").trim();
4298
+ agentText = agentText.replace(/\s*\[Prompted on:.*?\]/g, "").trim();
4299
+ await RevertManager.startTransaction(chatId, agentText);
4300
+ try {
4301
+ let modifiedHistory = [...history.slice(0, -1)];
4302
+ if (systemSettings?.compression === 0 && (sessionStats?.tokens || 0) > 254e3) {
4303
+ modifiedHistory = getTruncatedHistory(modifiedHistory, 6);
4166
4304
  }
4167
- if (TERMINATION_SIGNAL) {
4168
- yield { type: "status", content: "Termination Signal Received." };
4169
- await new Promise((resolve) => setTimeout(resolve, 1500));
4170
- break;
4305
+ if (isFirstPrompt && isMemoryEnabled) {
4306
+ yield { type: "status", content: "Condensing past chat memories..." };
4307
+ await consolidatePastMemories(chatId, settings);
4171
4308
  }
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 += `
4309
+ const tempStorage = readEncryptedJson(TEMP_MEM_FILE, {});
4310
+ const cacheStorage = readEncryptedJson(TEMP_MEM_CHAT_FILE, {});
4311
+ const otherRawMemories = Object.entries(tempStorage).filter(([id]) => id !== chatId).flatMap(([_, mems]) => mems);
4312
+ const cachedSummaries = Object.entries(cacheStorage).filter(([id]) => id !== chatId).slice(-20).map(([id, summary]) => `[Chat Summary]: ${summary}`);
4313
+ const otherMemories = [...cachedSummaries, ...otherRawMemories].map((mem) => `- ${mem}`).join("\n");
4314
+ const persistentStorage = readEncryptedJson(MEMORIES_FILE, []);
4315
+ const mainUserMemories = persistentStorage.map((m) => `- ${m.memory}`).join("\n");
4316
+ const isContext32k = (sessionStats?.tokens || 0) >= 32e3;
4317
+ const memoryPrompt = getMemoryPrompt(otherMemories, mainUserMemories, isMemoryEnabled, isContext32k);
4318
+ const dateTimeStr = (/* @__PURE__ */ new Date()).toLocaleString([], { year: "numeric", month: "numeric", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: true });
4319
+ const firstUserMsg = `${memoryPrompt}
4320
+ [METADATA (PRIORITY: DYNAMIC)] Time: ${dateTimeStr} | v${versionFluxflow2}
4321
+ ${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();
4322
+ modifiedHistory.push({ role: "user", text: firstUserMsg });
4323
+ let lastUsage = null;
4324
+ const MAX_LOOPS = mode === "Flux" ? 70 : 7;
4325
+ const MAX_RETRIES = 16;
4326
+ yield { type: "status", content: "Connecting..." };
4327
+ TERMINATION_SIGNAL = false;
4328
+ let fullAgentResponseChunks = [];
4329
+ let wasToolCalledInLastLoop = false;
4330
+ modifiedHistory.forEach((msg) => {
4331
+ if (msg.text && msg.role === "agent") {
4332
+ msg.text = msg.text.replace(/<(think|thought)>[\s\S]*?<\/(think|thought)>/gi, "").trim();
4333
+ }
4334
+ });
4335
+ for (let loop = 0; loop <= MAX_LOOPS; loop++) {
4336
+ if (loop > 0) {
4337
+ yield { type: "status", content: "Processed. Reconnecting..." };
4338
+ }
4339
+ if (TERMINATION_SIGNAL) {
4340
+ yield { type: "status", content: "Termination Signal Received." };
4341
+ await new Promise((resolve) => setTimeout(resolve, 1500));
4342
+ break;
4343
+ }
4344
+ if (steeringCallback) {
4345
+ const hint = await steeringCallback();
4346
+ if (hint) {
4347
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "user") {
4348
+ modifiedHistory[modifiedHistory.length - 1].text += `
4177
4349
 
4178
4350
  [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}` });
4351
+ } else {
4352
+ 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}` });
4353
+ }
4354
+ yield { type: "status", content: "Steering Hint Injected." };
4181
4355
  }
4182
- yield { type: "status", content: "Steering Hint Injected." };
4183
4356
  }
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`);
4357
+ let stream;
4358
+ let success = false;
4359
+ let retryCount = 1;
4360
+ let inStreamRetryCount = 1;
4361
+ let turnText = "";
4362
+ let lastToolSniffed = null;
4363
+ let lastToolDetail = null;
4364
+ let lastToolEventTime = null;
4365
+ let lastToolFinishedAt = 0;
4366
+ let toolResults = [];
4367
+ let toolCallPointer = 0;
4368
+ let anyToolExecutedInThisTurn = false;
4369
+ let isThinkingLoop = false;
4370
+ let isStutteringLoop = false;
4371
+ let isGeneralLoop = false;
4372
+ let isInitialAttempt = true;
4373
+ let accumulatedContext = "";
4374
+ let dedupeBuffer = "";
4375
+ let isDedupeActive = false;
4376
+ while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
4377
+ try {
4378
+ turnText = "";
4379
+ if (isInitialAttempt) {
4380
+ if (process.stdout.isTTY) {
4381
+ process.stdout.write(`\x1B]0;Working...\x07`);
4382
+ }
4383
+ yield { type: "turn_reset", content: true };
4384
+ yield { type: "spinner", content: true };
4385
+ isInitialAttempt = false;
4386
+ if (inStreamRetryCount === 1) {
4387
+ accumulatedContext = "";
4388
+ }
4210
4389
  }
4211
- yield { type: "turn_reset", content: true };
4212
- yield { type: "spinner", content: true };
4213
- isInitialAttempt = false;
4214
- if (inStreamRetryCount === 1) {
4215
- accumulatedContext = "";
4390
+ const contents = modifiedHistory.filter((msg) => (msg.role === "user" || msg.role === "agent" || msg.role === "system") && !String(msg.id).startsWith("welcome") && !msg.isMeta).map((msg) => {
4391
+ const parts = [{ text: msg.text }];
4392
+ if (msg.binaryPart) {
4393
+ parts.push(msg.binaryPart);
4394
+ }
4395
+ return {
4396
+ role: msg.role === "user" || msg.role === "system" ? "user" : "model",
4397
+ parts
4398
+ };
4399
+ });
4400
+ if (!await checkQuota("agent", settings)) {
4401
+ throw new Error("Error: Daily Quota Exausted for Agent");
4216
4402
  }
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);
4403
+ let targetModel = modelName;
4404
+ if (retryCount === MAX_RETRIES - 1) {
4405
+ targetModel = "gemini-3-flash-preview";
4406
+ yield { type: "model_update", content: "Trying with fallback model" };
4407
+ } else if (retryCount === MAX_RETRIES) {
4408
+ targetModel = "gemini-3.5-flash";
4409
+ yield { type: "model_update", content: "Trying with fallback model" };
4410
+ } else if (retryCount > 12 && retryCount < MAX_RETRIES - 2 && settings.apiKey !== "custom") {
4411
+ targetModel = "gemma-4-31b-it";
4412
+ yield { type: "model_update", content: "Trying with fallback Gemma Model" };
4413
+ } else if (retryCount > 0) {
4414
+ yield { type: "model_update", content: null };
4222
4415
  }
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 = `
4416
+ const currentSystemInstruction = getSystemInstruction(profile, thinkingLevel, mode, systemSettings, isMemoryEnabled, MAX_LOOPS, loop + 1);
4417
+ const jitInstruction = `
4246
4418
 
4247
4419
  [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 += `
4420
+ const lastUserMsg = contents[contents.length - 1];
4421
+ let addedMarker = false;
4422
+ if (lastUserMsg && lastUserMsg.role === "user" && lastUserMsg.parts?.[0]?.text?.startsWith("[TOOL RESULT]")) {
4423
+ lastUserMsg.parts[0].text += jitInstruction;
4424
+ addedMarker = true;
4425
+ }
4426
+ const stepThreshold = Math.floor(MAX_LOOPS * (mode === "Flux" ? 0.95 : 0.7));
4427
+ const currentStep = loop + 1;
4428
+ if (currentStep >= stepThreshold && lastUserMsg && lastUserMsg.parts?.[0]) {
4429
+ lastUserMsg.parts[0].text += `
4258
4430
  [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
4431
  }
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;
4432
+ stream = await client.models.generateContentStream({
4433
+ model: targetModel || "gemma-4-31b-it",
4434
+ contents,
4435
+ config: {
4436
+ systemInstruction: currentSystemInstruction,
4437
+ temperature: mode === "Flux" ? 1 : 1.4,
4438
+ maxOutputTokens: 32768,
4439
+ mediaResolution: "MEDIA_RESOLUTION_MEDIUM",
4440
+ safetySettings: [
4441
+ { category: HarmCategory.HARM_CATEGORY_HARASSMENT, threshold: HarmBlockThreshold.BLOCK_NONE },
4442
+ { category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, threshold: HarmBlockThreshold.BLOCK_NONE },
4443
+ { category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, threshold: HarmBlockThreshold.BLOCK_NONE },
4444
+ { category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, threshold: HarmBlockThreshold.BLOCK_NONE }
4445
+ ],
4446
+ thinkingConfig: { includeThoughts: false, thinkingLevel: targetModel.includes("pro") ? ThinkingLevel.HIGH : ThinkingLevel.MINIMAL }
4447
+ }
4448
+ });
4449
+ if (addedMarker && contents[contents.length - 1]?.parts?.[0]) {
4450
+ contents[contents.length - 1].parts[0].text = contents[contents.length - 1].parts[0].text.replace(jitInstruction, "").trim();
4294
4451
  }
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;
4452
+ turnText = "";
4453
+ lastToolSniffed = null;
4454
+ lastToolEventTime = null;
4455
+ toolResults = [];
4456
+ toolCallPointer = 0;
4457
+ yield { type: "model_update", content: null };
4458
+ yield { type: "status", content: "Working..." };
4459
+ dedupeBuffer = "";
4460
+ isDedupeActive = accumulatedContext.length > 0;
4461
+ for await (const chunk of stream) {
4462
+ if (TERMINATION_SIGNAL) {
4463
+ yield { type: "status", content: "Termination Signal Received." };
4464
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4465
+ break;
4466
+ }
4467
+ if (chunk.text) {
4468
+ if (isDedupeActive) {
4469
+ dedupeBuffer += chunk.text;
4470
+ if (dedupeBuffer.length >= 30) {
4471
+ let overlapLen = 0;
4472
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4473
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4474
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4475
+ overlapLen = len;
4476
+ break;
4477
+ }
4305
4478
  }
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 };
4479
+ const cleanText = dedupeBuffer.substring(overlapLen);
4480
+ if (cleanText) {
4481
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4482
+ 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, "");
4483
+ if (dedupeClean) {
4484
+ turnText += dedupeClean;
4485
+ yield { type: "text", content: dedupeClean };
4486
+ }
4314
4487
  }
4488
+ isDedupeActive = false;
4489
+ dedupeBuffer = "";
4315
4490
  }
4316
- isDedupeActive = false;
4317
- dedupeBuffer = "";
4491
+ continue;
4492
+ } else {
4493
+ turnText += chunk.text;
4494
+ yield { type: "text", content: chunk.text };
4318
4495
  }
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, "/"));
4496
+ const signalSafeText3 = getSanitizedText(turnText);
4497
+ const toolContext = getActiveToolContext(turnText);
4498
+ if (toolContext.inside) {
4499
+ if (!lastToolEventTime) lastToolEventTime = Date.now();
4500
+ const rawToolName = toolContext.toolName;
4501
+ const NORMALIZE_MAP = {
4502
+ "Ask": "ask",
4503
+ "WebSearch": "web_search",
4504
+ "WebScrape": "web_scrape",
4505
+ "ReadFile": "view_file",
4506
+ "ReadFolder": "read_folder",
4507
+ "WriteFile": "write_file",
4508
+ "PatchFile": "update_file",
4509
+ "WritePDF": "write_pdf",
4510
+ "WriteDoc": "write_docx",
4511
+ "Run": "exec_command",
4512
+ "SearchKeyword": "search_keyword",
4513
+ "Memory": "memory",
4514
+ "Chat": "chat",
4515
+ "chat": "chat",
4516
+ "GenerateImage": "generate_image",
4517
+ "generate_image": "generate_image"
4518
+ };
4519
+ const potentialTool = NORMALIZE_MAP[rawToolName] || rawToolName;
4520
+ const partialArgs = toolContext.args || "";
4521
+ let detail = null;
4522
+ if (["write_file", "update_file", "view_file", "read_folder", "write_pdf", "write_docx", "search_keyword", "generate_image"].includes(potentialTool)) {
4523
+ const pArgs = parseArgs(partialArgs);
4524
+ const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
4525
+ const keyword = pArgs.keyword;
4526
+ if (keyword) {
4527
+ detail = keyword.replace(/["']/g, "");
4528
+ } else if (filePath) {
4529
+ detail = path15.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
4530
+ } else {
4531
+ const m = partialArgs.match(/(?:path|targetFile|TargetFile|directory|keyword)\s*=\s*\\?["']?([^\\"' \),]+)/);
4532
+ if (m) {
4533
+ const val = m[1].replace(/["']/g, "");
4534
+ detail = potentialTool === "search_keyword" ? val : path15.basename(val.replace(/\\/g, "/"));
4535
+ }
4363
4536
  }
4364
4537
  }
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;
4538
+ const currentLabel = `${TOOL_LABELS2[potentialTool] || potentialTool}${detail ? ` (${detail})` : ""}`;
4539
+ if (potentialTool !== lastToolSniffed || detail !== lastToolDetail) {
4540
+ lastToolSniffed = potentialTool;
4541
+ lastToolDetail = detail;
4542
+ yield { type: "status", content: `${currentLabel}...` };
4543
+ if (process.stdout.isTTY) {
4544
+ const TOOL_TITLES = {
4545
+ "web_search": "Searching Web",
4546
+ "web_scrape": "Reading Website",
4547
+ "view_file": "Reading File",
4548
+ "read_folder": "Listing Folder",
4549
+ "list_files": "Listing Folder",
4550
+ "write_file": "Writing File",
4551
+ "update_file": "Updating File",
4552
+ "write_pdf": "Creating PDF",
4553
+ "write_docx": "Creating Word Doc",
4554
+ "search_keyword": "Searching Keywords",
4555
+ "exec_command": "Running Command",
4556
+ "ask": "Asking User",
4557
+ "memory": "Updating Memory",
4558
+ "generate_image": "Generating Image"
4559
+ };
4560
+ const toolTitle = TOOL_TITLES[potentialTool] || "Working";
4561
+ process.stdout.write(`\x1B]0;${toolTitle}...\x07`);
4443
4562
  }
4444
4563
  }
4445
- if (isRepeating) {
4446
- stutterDetected = true;
4447
- break;
4448
- }
4449
4564
  }
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);
4565
+ const contextSafeText = getContextSafeText(turnText, false);
4566
+ const thinkBlocks = contextSafeText.match(/<think>([\s\S]*?)(?:<\/think>|$)/gi) || [];
4567
+ const thinkContent = thinkBlocks.join("").trim();
4568
+ const sentences = thinkContent.split(/[.!?]\s+/);
4569
+ const uniqueSentences = new Set(sentences);
4570
+ const repetitionRatio = sentences.length > 10 ? (sentences.length - uniqueSentences.size) / sentences.length : 0;
4571
+ const wordCount = thinkContent.split(/\s+/).filter((w) => w.length > 0).length;
4572
+ let repetitionThresholdThinking = 0.4;
4573
+ let repetitionThresholdResponse = 0.6;
4574
+ const thinkingCaps = {
4575
+ "low": 200,
4576
+ "medium": 500,
4577
+ "high": 2e3,
4578
+ "max": 3500,
4579
+ "xhigh": 3500
4580
+ };
4581
+ const cap = thinkingCaps[thinkingLevel?.toLowerCase()] || 2500;
4582
+ let isOverVerboseThinking = wordCount > cap;
4583
+ if (repetitionRatio > repetitionThresholdThinking || isOverVerboseThinking) {
4584
+ const reason = repetitionRatio > repetitionThresholdThinking ? "Thinking Loop Detected" : "Thinking Budget Exceeded";
4585
+ yield { type: "status", content: `${reason}. Re-centering...` };
4586
+ isThinkingLoop = true;
4587
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4588
+ break;
4589
+ }
4590
+ const responseContent = signalSafeText3.trim();
4591
+ const respSentences = responseContent.split(/[.!?]\s+/);
4592
+ const uniqueRespSentences = new Set(respSentences);
4593
+ const respRepetitionRatio = respSentences.length > 10 ? (respSentences.length - uniqueRespSentences.size) / respSentences.length : 0;
4594
+ if (respRepetitionRatio > repetitionThresholdResponse) {
4595
+ yield { type: "status", content: `Response Loop Detected. Re-centering...` };
4596
+ isThinkingLoop = false;
4597
+ isGeneralLoop = true;
4598
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4599
+ break;
4600
+ }
4601
+ const allWords = contextSafeText.toLowerCase().split(/\s+/).filter((w) => w.length > 0);
4602
+ let stutterDetected = false;
4603
+ if (allWords.length > 5) {
4604
+ for (let p = 1; p <= 15; p++) {
4605
+ const R = Math.max(3, Math.ceil(8 / p));
4606
+ if (allWords.length < p * R) continue;
4458
4607
  let isRepeating = true;
4608
+ const pattern = allWords.slice(allWords.length - p);
4609
+ const patternStr = pattern.join(" ");
4459
4610
  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) {
4611
+ const prevPattern = allWords.slice(allWords.length - p * (r + 1), allWords.length - p * r);
4612
+ if (prevPattern.join(" ") !== patternStr) {
4462
4613
  isRepeating = false;
4463
4614
  break;
4464
4615
  }
@@ -4469,400 +4620,424 @@ ${thinkingLevel != "Fast" ? "[SYSTEM] **STRICTLY FOLLOW THINKING POLICY AS CORE
4469
4620
  }
4470
4621
  }
4471
4622
  }
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);
4623
+ if (!stutterDetected) {
4624
+ const cleanChars = contextSafeText.toLowerCase().replace(/[^a-z0-9]/gi, "");
4625
+ if (cleanChars.length >= 10) {
4626
+ for (let p = 1; p <= 10; p++) {
4627
+ const R = Math.max(4, Math.ceil(12 / p));
4628
+ if (cleanChars.length < p * R) continue;
4629
+ const pattern = cleanChars.substring(cleanChars.length - p);
4630
+ let isRepeating = true;
4631
+ for (let r = 1; r < R; r++) {
4632
+ const prevPattern = cleanChars.substring(cleanChars.length - p * (r + 1), cleanChars.length - p * r);
4633
+ if (prevPattern !== pattern) {
4634
+ isRepeating = false;
4635
+ break;
4636
+ }
4637
+ }
4638
+ if (isRepeating) {
4639
+ stutterDetected = true;
4640
+ break;
4641
+ }
4528
4642
  }
4529
- } catch (e) {
4530
4643
  }
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();
4644
+ }
4645
+ if (stutterDetected) {
4646
+ yield { type: "status", content: `Stuttering Detected. Re-centering...` };
4647
+ isThinkingLoop = false;
4648
+ isStutteringLoop = true;
4649
+ await new Promise((resolve) => setTimeout(resolve, 3e3));
4650
+ break;
4651
+ }
4652
+ const toolActionableText = turnText.replace(/<think>[\s\S]*?(?:<\/think>|$)/gi, "");
4653
+ const allToolsFound = detectToolCalls(toolActionableText);
4654
+ while (allToolsFound.length > toolCallPointer) {
4655
+ const toolCall = allToolsFound[toolCallPointer];
4656
+ const NORMALIZE_MAP = {
4657
+ "Ask": "ask",
4658
+ "WebSearch": "web_search",
4659
+ "WebScrape": "web_scrape",
4660
+ "ReadFile": "view_file",
4661
+ "ReadFolder": "read_folder",
4662
+ "WriteFile": "write_file",
4663
+ "PatchFile": "update_file",
4664
+ "WritePDF": "write_pdf",
4665
+ "WriteDoc": "write_docx",
4666
+ "Run": "exec_command",
4667
+ "SearchKeyword": "search_keyword",
4668
+ "Memory": "memory",
4669
+ "Chat": "chat",
4670
+ "chat": "chat",
4671
+ "GenerateImage": "generate_image",
4672
+ "generate_image": "generate_image"
4673
+ };
4674
+ const normToolName = NORMALIZE_MAP[toolCall.toolName] || toolCall.toolName;
4675
+ const displayLabel = TOOL_LABELS2[normToolName] || toolCall.toolName;
4676
+ const detail = getToolDetail(normToolName, toolCall.args);
4677
+ yield { type: "status", content: `${displayLabel}${detail ? ` (${detail})` : ""}...` };
4678
+ let label = "";
4679
+ if (normToolName === "web_search") {
4680
+ const { query, limit = 10 } = parseArgs(toolCall.args);
4681
+ label = `\u{1F50D} SEARCHED: "${query}" (${limit})`.toUpperCase();
4682
+ } else if (normToolName === "web_scrape") {
4683
+ const url = parseArgs(toolCall.args).url || "...";
4684
+ label = `\u{1F4D6} READ SITE: ${url}`.toUpperCase();
4685
+ } else if (normToolName === "view_file") {
4686
+ const { path: targetPath2, StartLine, EndLine, start_line, end_line } = parseArgs(toolCall.args);
4687
+ const rawStart = StartLine || start_line;
4688
+ const rawEnd = EndLine || end_line;
4689
+ const sLine = parseInt(rawStart) || 1;
4690
+ const eLine = parseInt(rawEnd) || (rawStart ? sLine + 800 : 800);
4691
+ let totalLines = "...";
4692
+ let actualEndLine = eLine;
4693
+ try {
4694
+ const absPath = path15.resolve(process.cwd(), targetPath2);
4695
+ if (fs16.existsSync(absPath)) {
4696
+ const content = fs16.readFileSync(absPath, "utf8");
4697
+ const lines = content.split("\n").length;
4698
+ totalLines = lines;
4699
+ actualEndLine = Math.min(eLine, lines);
4700
+ }
4701
+ } catch (e) {
4702
+ }
4703
+ const pathLower = targetPath2.toLowerCase();
4704
+ const isPdf = pathLower.endsWith(".pdf");
4705
+ const isImage = /\.(png|jpg|jpeg|webp|gif|bmp)$/.test(pathLower);
4706
+ if (isPdf) {
4707
+ label = `\u{1F4C4} ANALYZED PDF: ${targetPath2}`.toUpperCase();
4708
+ } else if (isImage) {
4709
+ label = `\u{1F4F8} ANALYZED IMAGE: ${targetPath2}`.toUpperCase();
4710
+ } else {
4711
+ label = `\u{1F4C4} ANALYZED FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
4712
+ }
4713
+ } else if (normToolName === "list_files" || normToolName === "read_folder") {
4714
+ const action = normToolName === "list_files" ? "LIST" : "ANALYSED";
4715
+ label = `\u{1F4C2} ${action} FOLDER: ${parseArgs(toolCall.args).path || "."}`.toUpperCase();
4716
+ } else if (normToolName === "write_file" || normToolName === "update_file") {
4717
+ const action = normToolName === "write_file" ? "WRITTEN" : "UPDATED FILE";
4718
+ label = `\u{1F4BE} ${action}: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4719
+ } else if (normToolName === "write_pdf") {
4720
+ label = `\u{1F4D1} PDF CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4721
+ } else if (normToolName === "write_docx") {
4722
+ label = `\u{1F4DD} DOCX CREATED: ${parseArgs(toolCall.args).path || "..."}`.toUpperCase();
4723
+ } else if (normToolName === "search_keyword") {
4724
+ const { keyword } = parseArgs(toolCall.args);
4725
+ label = `\u{1F50E} KEYWORD SEARCHED: "${keyword}"`.toUpperCase();
4726
+ } else if (normToolName === "generate_image") {
4727
+ const { path: argPath, outputPath, output } = parseArgs(toolCall.args);
4728
+ label = `\u{1F3A8} IMAGE GENERATED: ${argPath || outputPath || output || "generated_image.png"}`.toUpperCase();
4729
+ } else if (normToolName === "exec_command" || normToolName === "ask") {
4730
+ label = "";
4538
4731
  } else {
4539
- label = `\u{1F4C4} ANALYZED FILE: ${targetPath2} | LINES: ${sLine}-${actualEndLine} OF ${totalLines}`.toUpperCase();
4732
+ label = `EXECUTED: ${toolCall.toolName}`.toUpperCase();
4540
4733
  }
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}
4734
+ if (label) {
4735
+ const boxWidth = Math.min(label.length + 4, 115);
4736
+ const boxTop = `\u256D${"\u2500".repeat(boxWidth)}\u256E`;
4737
+ const boxMid = `\u2502 ${label.padEnd(boxWidth - 2).substring(0, boxWidth - 2)} \u2502`;
4738
+ const boxBottom = `\u2570${"\u2500".repeat(boxWidth)}\u256F`;
4739
+ yield { type: "visual_feedback", content: `${boxTop}
4568
4740
  ${boxMid}
4569
4741
  ${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;
4742
+ }
4743
+ if (normToolName === "exec_command") {
4744
+ const { command } = parseArgs(toolCall.args);
4745
+ if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
4746
+ const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
4747
+ const currentDrive = path15.resolve(process.cwd()).substring(0, 3).toLowerCase();
4748
+ const isViolating = riskyPatterns.some((pattern) => {
4749
+ if (pattern.source === "[a-zA-Z]:[\\\\\\/]") {
4750
+ const driveMatch = command.match(/[a-zA-Z]:[\\\/]/i);
4751
+ return driveMatch && driveMatch[0].toLowerCase() !== currentDrive;
4752
+ }
4753
+ return pattern.test(command);
4754
+ });
4755
+ if (isViolating) {
4756
+ const denyMsg = `Access Denied. Terminal is prohibited from accessing system drives (C://) or external directories while "External Workspace Access" is disabled.`;
4757
+ toolResults.push({ role: "user", text: `[TOOL RESULT]: ERROR: ${denyMsg}` });
4758
+ yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
4759
+ toolCallPointer++;
4760
+ continue;
4580
4761
  }
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}` });
4762
+ }
4763
+ if (settings.onExecStart) settings.onExecStart(command || "Unknown");
4764
+ yield { type: "exec_start" };
4765
+ }
4766
+ const parsedArgs = parseArgs(toolCall.args);
4767
+ const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
4768
+ if (targetPath) {
4769
+ const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
4770
+ const absoluteTarget = path15.resolve(targetPath);
4771
+ const absoluteCwd = path15.resolve(process.cwd());
4772
+ if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
4773
+ 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.`;
4774
+ 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
4775
  yield { type: "tool_result", content: `[TOOL RESULT]: ERROR: ${denyMsg}` };
4587
4776
  toolCallPointer++;
4588
4777
  continue;
4589
4778
  }
4590
4779
  }
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;
4780
+ if (settings.onToolApproval) {
4781
+ let shouldPrompt = normToolName === "write_file" || normToolName === "update_file" || normToolName === "exec_command";
4782
+ if (shouldPrompt) {
4783
+ const approval = await settings.onToolApproval(normToolName, toolCall.args);
4784
+ if (approval === "deny") {
4785
+ if (normToolName === "exec_command" && settings.onExecEnd) settings.onExecEnd();
4786
+ const denyMsg = `Permission Denied: User rejected the ${normToolName === "exec_command" ? "terminal execution" : "file edit"}.`;
4787
+ 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**" : ""}` });
4788
+ yield { type: "tool_result", content: `[TOOL RESULT]: DENIED: ${denyMsg}` };
4789
+ await incrementUsage("toolDenied");
4790
+ if (settings.onToolResult) settings.onToolResult("denied", normToolName);
4791
+ toolCallPointer++;
4792
+ continue;
4793
+ }
4794
+ }
4606
4795
  }
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;
4796
+ if (lastToolFinishedAt > 0) {
4797
+ const timeSinceLastTool = Date.now() - lastToolFinishedAt;
4798
+ if (timeSinceLastTool < 1e3) {
4799
+ await new Promise((resolve) => setTimeout(resolve, 1e3 - timeSinceLastTool));
4621
4800
  }
4622
4801
  }
4623
- }
4624
- if (lastToolFinishedAt > 0) {
4625
- const timeSinceLastTool = Date.now() - lastToolFinishedAt;
4626
- if (timeSinceLastTool < 1e3) {
4627
- await new Promise((resolve) => setTimeout(resolve, 1e3 - timeSinceLastTool));
4802
+ const effectiveStart = lastToolEventTime || Date.now();
4803
+ yield { type: "spinner", content: false };
4804
+ let result = await dispatchTool(normToolName, toolCall.args, {
4805
+ chatId,
4806
+ history,
4807
+ onChunk: (chunk2) => settings.onExecChunk ? settings.onExecChunk(chunk2) : null,
4808
+ onAskUser: settings.onAskUser
4809
+ });
4810
+ yield { type: "spinner", content: true };
4811
+ if (process.stdout.isTTY) {
4812
+ process.stdout.write(`\x1B]0;Working...\x07`);
4628
4813
  }
4814
+ const toolEnd = Date.now();
4815
+ lastToolFinishedAt = toolEnd;
4816
+ yield { type: "tool_time", content: toolEnd - effectiveStart };
4817
+ lastToolEventTime = toolEnd;
4818
+ let binaryPart = null;
4819
+ if (typeof result === "object" && result.binaryPart) {
4820
+ binaryPart = result.binaryPart;
4821
+ result = result.text;
4822
+ }
4823
+ if (normToolName === "exec_command" && settings.onExecEnd) {
4824
+ await new Promise((resolve) => setTimeout(resolve, 800));
4825
+ settings.onExecEnd();
4826
+ }
4827
+ const isDenied = result && result.startsWith("DENIED:");
4828
+ const isSuccess = result && !result.startsWith("ERROR:") && !isDenied;
4829
+ if (isSuccess) {
4830
+ await incrementUsage("toolSuccess");
4831
+ if (settings.onToolResult) settings.onToolResult("success", normToolName);
4832
+ } else if (isDenied) {
4833
+ } else {
4834
+ await incrementUsage("toolFailure");
4835
+ if (settings.onToolResult) settings.onToolResult("failure", normToolName);
4836
+ }
4837
+ const aiContent = `[TOOL RESULT]: ${(result || "").toString().split(/\r?\n/).filter((line) => !line.includes("[UI_CONTEXT]")).join("\n")}`;
4838
+ toolResults.push({ role: "user", text: aiContent, binaryPart });
4839
+ anyToolExecutedInThisTurn = true;
4840
+ let uiContent = `[TOOL RESULT]: ${result || ""}`;
4841
+ if (normToolName === "view_file" || normToolName === "web_scrape") {
4842
+ uiContent = `[TOOL RESULT]: ${label} (Context Locked for UI Clarity)`;
4843
+ }
4844
+ yield { type: "tool_result", content: uiContent, aiContent, binaryPart, toolName: normToolName };
4845
+ if (normToolName === "memory" && result.includes("SUCCESS")) yield { type: "memory_updated" };
4846
+ toolCallPointer++;
4629
4847
  }
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
4848
  }
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;
4849
+ lastUsage = chunk.usageMetadata;
4850
+ if (lastUsage) {
4851
+ yield { type: "liveTokens", content: lastUsage.totalTokenCount };
4689
4852
  }
4690
4853
  }
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 };
4854
+ if (isDedupeActive && dedupeBuffer.length > 0) {
4855
+ let overlapLen = 0;
4856
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4857
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4858
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4859
+ overlapLen = len;
4860
+ break;
4861
+ }
4698
4862
  }
4863
+ const cleanText = dedupeBuffer.substring(overlapLen);
4864
+ if (cleanText) {
4865
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4866
+ 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, "");
4867
+ if (dedupeClean) {
4868
+ turnText += dedupeClean;
4869
+ yield { type: "text", content: dedupeClean };
4870
+ }
4871
+ }
4872
+ isDedupeActive = false;
4873
+ dedupeBuffer = "";
4874
+ }
4875
+ if (TERMINATION_SIGNAL) break;
4876
+ const signalSafeText2 = (turnText || "").trim();
4877
+ const hasFinish2 = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText2.toLowerCase());
4878
+ const hasContinue = /\[\s*(turn\s*:)?\s*continue\s*\]/i.test(signalSafeText2.toLowerCase());
4879
+ const didCallTool = toolResults.length > 0 || lastToolSniffed !== null;
4880
+ const pureOutputText = signalSafeText2.replace(/<think>[\s\S]*?<\/think>/gi, "").trim();
4881
+ const endsNormally = /[.!?}"'`’“”]$|```$/s.test(pureOutputText);
4882
+ if (!hasFinish2 && !hasContinue && !didCallTool && signalSafeText2.length > 0 && !endsNormally && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop) {
4883
+ throw new Error("Silent stream cutoff (500): Model stream closed cleanly but cut off mid-sentence without signals.");
4699
4884
  }
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
4885
  success = true;
4718
4886
  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
- }
4887
+ } catch (err) {
4888
+ if (String(err).includes("Incomplete JSON segment at the end")) {
4889
+ success = true;
4890
+ await incrementUsage("agent");
4891
+ break;
4729
4892
  }
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;
4893
+ if (isDedupeActive && dedupeBuffer.length > 0) {
4894
+ let overlapLen = 0;
4895
+ const maxPossibleOverlap = Math.min(accumulatedContext.length, dedupeBuffer.length);
4896
+ for (let len = maxPossibleOverlap; len > 0; len--) {
4897
+ if (accumulatedContext.endsWith(dedupeBuffer.substring(0, len))) {
4898
+ overlapLen = len;
4899
+ break;
4900
+ }
4736
4901
  }
4902
+ const cleanText = dedupeBuffer.substring(overlapLen);
4903
+ if (cleanText) {
4904
+ const hasOpenThink = /<(think|thought)>(?:(?!<\/(?:think|thought)>)[\s\S])*$/i.test(accumulatedContext);
4905
+ 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, "");
4906
+ if (dedupeClean) {
4907
+ turnText += dedupeClean;
4908
+ }
4909
+ }
4910
+ isDedupeActive = false;
4911
+ dedupeBuffer = "";
4737
4912
  }
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}
4913
+ const errMsg = err.status || err.error && err.error.message || String(err);
4914
+ const errLog = String(err);
4915
+ const date = (/* @__PURE__ */ new Date()).toLocaleString();
4916
+ const agentErrDir = path15.join(LOGS_DIR, "agent");
4917
+ if (!fs16.existsSync(agentErrDir)) fs16.mkdirSync(agentErrDir, { recursive: true });
4918
+ fs16.appendFileSync(path15.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
4747
4919
 
4748
4920
  ----------------------------------------------------------------------
4749
4921
 
4750
4922
  `);
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;
4923
+ const status = err.status || err.statusCode || err.code;
4924
+ 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)));
4925
+ if (!isRetryable) {
4926
+ if (retryCount < MAX_RETRIES - 3) {
4927
+ throw err;
4928
+ }
4756
4929
  }
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}
4930
+ if (turnText.trim().length > 0 || inStreamRetryCount > 1) {
4931
+ if (inStreamRetryCount <= MAX_RETRIES) {
4932
+ inStreamRetryCount++;
4933
+ const waitTime = Math.min(1e3 * Math.pow(2, inStreamRetryCount - 1), 24e3);
4934
+ if (turnText.trim().length > 0) {
4935
+ modifiedHistory.push({ role: "agent", text: turnText });
4936
+ 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.";
4937
+ if (toolResults.length > 0) {
4938
+ toolResults.forEach((tr, idx) => {
4939
+ if (idx === toolResults.length - 1) {
4940
+ modifiedHistory.push({
4941
+ ...tr,
4942
+ text: `${tr.text}
4771
4943
 
4772
4944
  ${recoveryText}`
4773
- });
4774
- } else {
4775
- modifiedHistory.push(tr);
4776
- }
4777
- });
4778
- } else {
4779
- modifiedHistory.push({ role: "user", text: recoveryText });
4945
+ });
4946
+ } else {
4947
+ modifiedHistory.push(tr);
4948
+ }
4949
+ });
4950
+ } else {
4951
+ modifiedHistory.push({ role: "user", text: recoveryText });
4952
+ }
4953
+ accumulatedContext += turnText;
4780
4954
  }
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));
4955
+ for (let i = waitTime / 1e3; i > 0; i--) {
4956
+ yield { type: "status", content: `Error Occured. Recovering Stream (${inStreamRetryCount}/${MAX_RETRIES}) [${i}s]...` };
4957
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
4958
+ }
4959
+ yield { type: "status", content: `Error Occured. Recovering Stream...` };
4960
+ } else {
4961
+ throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
4962
+ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4786
4963
  }
4787
- yield { type: "status", content: `Error Occured. Recovering Stream...` };
4788
4964
  } 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));
4965
+ if (retryCount <= MAX_RETRIES) {
4966
+ retryCount++;
4967
+ inStreamRetryCount = 1;
4968
+ accumulatedContext = "";
4969
+ const waitTime = Math.min(1e3 * Math.pow(2, retryCount - 1), 32e3);
4970
+ isInitialAttempt = true;
4971
+ yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${(waitTime / 1e3).toFixed(0)}s]...` };
4972
+ for (let i = waitTime / 1e3; i > 0; i--) {
4973
+ yield { type: "status", content: `Retrying Connection (${retryCount}/${MAX_RETRIES}) [${i}s]...` };
4974
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
4975
+ }
4976
+ yield { type: "status", content: `Retrying Connection...` };
4977
+ } else {
4978
+ throw new Error(`Model cannot be reached. (Failed ${MAX_RETRIES} times)
4979
+ Error Log can be found in ${path15.join(LOGS_DIR, "agent", "error.log")}`);
4803
4980
  }
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
4981
  }
4809
4982
  }
4810
4983
  }
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}
4984
+ if (lastUsage) {
4985
+ await addToUsage("tokens", lastUsage.totalTokenCount || 0);
4986
+ yield { type: "usage", content: lastUsage };
4987
+ }
4988
+ fullAgentResponseChunks.push(turnText);
4989
+ let textToProcess = turnText;
4990
+ const thinkMatch = turnText.match(/<think>([\s\S]*?)<\/think>/i);
4991
+ if (thinkMatch) {
4992
+ textToProcess = turnText.replace(/<think>[\s\S]*?<\/think>/i, "");
4993
+ }
4994
+ const signalSafeText = getSanitizedText(turnText);
4995
+ const hasFinish = /\[\s*(turn\s*:)?\s*finish\s*\]/i.test(signalSafeText.toLowerCase());
4996
+ const shouldContinue = toolCallPointer > 0;
4997
+ yield { type: "status", content: "Working..." };
4998
+ const cleanedTurnText = contextSafeReplace(turnText, /\[\s*(turn\s*:)?\s*(continue|finish)\s*\]/gi, "").trim();
4999
+ let isActuallyFinished = hasFinish && !shouldContinue;
5000
+ if (isActuallyFinished) {
5001
+ const fullAgentTextRaw = fullAgentResponseChunks.join("\n");
5002
+ const cleanedFullResponse = fullAgentTextRaw.replace(/<think>[\s\S]*?<\/think>/g, "").trim();
5003
+ yield {
5004
+ type: "interactive_turn_finished",
5005
+ data: {
5006
+ agentText,
5007
+ fullAgentTextRaw,
5008
+ history: [...modifiedHistory],
5009
+ needTitle
5010
+ }
5011
+ };
5012
+ const timestamp = `Responded on ${(/* @__PURE__ */ new Date()).toLocaleString()}`;
5013
+ const finalWithTime = `${cleanedFullResponse}
4842
5014
 
4843
5015
  ${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 });
5016
+ if (modifiedHistory.length > 0 && modifiedHistory[modifiedHistory.length - 1].role === "agent") {
5017
+ modifiedHistory[modifiedHistory.length - 1].text = finalWithTime;
5018
+ } else {
5019
+ modifiedHistory.push({ role: "agent", text: finalWithTime });
5020
+ }
4848
5021
  }
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.` });
5022
+ if (isActuallyFinished) break;
5023
+ const nextAgentMsg = cleanedTurnText.trim() || "*Working...*";
5024
+ modifiedHistory.push({ role: "agent", text: nextAgentMsg });
5025
+ if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
5026
+ toolResults.forEach((tr) => modifiedHistory.push(tr));
4858
5027
  } 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."}`}` });
5028
+ if (wasToolCalledInLastLoop) {
5029
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] System executed the tool with no explicit result, continue with your task or use [turn: finish] if completed.` });
5030
+ } else {
5031
+ 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."}`}` });
5032
+ }
5033
+ isThinkingLoop = false;
5034
+ isStutteringLoop = false;
5035
+ isGeneralLoop = false;
4860
5036
  }
4861
- isThinkingLoop = false;
4862
- isStutteringLoop = false;
4863
- isGeneralLoop = false;
5037
+ wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
4864
5038
  }
4865
- wasToolCalledInLastLoop = toolCallPointer > 0 || anyToolExecutedInThisTurn;
5039
+ } finally {
5040
+ await RevertManager.commitTransaction();
4866
5041
  }
4867
5042
  yield { type: "status", content: null };
4868
5043
  };
@@ -5113,11 +5288,92 @@ var init_UpdateProcessor = __esm({
5113
5288
  }
5114
5289
  });
5115
5290
 
5291
+ // src/components/RevertModal.jsx
5292
+ import React10, { useState as useState7 } from "react";
5293
+ import { Box as Box10, Text as Text10, useInput as useInput4 } from "ink";
5294
+ function RevertModal({ prompts, onSelect, onClose }) {
5295
+ const [selectedIndex, setSelectedIndex] = useState7(0);
5296
+ useInput4((input, key) => {
5297
+ if (key.escape) onClose();
5298
+ if (key.upArrow) setSelectedIndex((prev) => Math.max(0, prev - 1));
5299
+ if (key.downArrow) setSelectedIndex((prev) => Math.min(prompts.length - 1, prev + 1));
5300
+ if (key.return && prompts[selectedIndex]) onSelect(prompts[selectedIndex].id);
5301
+ });
5302
+ const s = emojiSpace(2);
5303
+ const MAX_VISIBLE = 10;
5304
+ let startIndex = 0;
5305
+ if (prompts.length > MAX_VISIBLE) {
5306
+ const half = Math.floor(MAX_VISIBLE / 2);
5307
+ startIndex = selectedIndex - half;
5308
+ if (startIndex < 0) {
5309
+ startIndex = 0;
5310
+ } else if (startIndex + MAX_VISIBLE > prompts.length) {
5311
+ startIndex = prompts.length - MAX_VISIBLE;
5312
+ }
5313
+ }
5314
+ const visiblePrompts = prompts.slice(startIndex, startIndex + MAX_VISIBLE);
5315
+ 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) => {
5316
+ const actualIndex = startIndex + index;
5317
+ const isSelected = actualIndex === selectedIndex;
5318
+ const dateStr = formatDate2(p.timestamp);
5319
+ const fileCount = p.changes ? p.changes.length : 0;
5320
+ return /* @__PURE__ */ React10.createElement(
5321
+ Box10,
5322
+ {
5323
+ key: p.id,
5324
+ paddingX: 1,
5325
+ backgroundColor: isSelected ? "#1a2a3a" : void 0,
5326
+ width: "100%"
5327
+ },
5328
+ /* @__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]")))
5329
+ );
5330
+ }), 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(
5331
+ Box10,
5332
+ {
5333
+ marginTop: 1,
5334
+ paddingX: 1,
5335
+ borderStyle: "single",
5336
+ borderLeft: false,
5337
+ borderRight: false,
5338
+ borderBottom: false,
5339
+ borderColor: "cyan"
5340
+ },
5341
+ /* @__PURE__ */ React10.createElement(Text10, { dimColor: true, italic: true }, "\u2191\u2193 navigate \u2022 Enter select undo point \u2022 Esc close")
5342
+ ));
5343
+ }
5344
+ function formatPromptPreview(prompt) {
5345
+ if (!prompt) return "";
5346
+ const firstLine = prompt.split("\n")[0] || "";
5347
+ const words = firstLine.split(/\s+/).filter(Boolean);
5348
+ if (words.length > 50) {
5349
+ return words.slice(0, 50).join(" ") + "...";
5350
+ }
5351
+ if (prompt.includes("\n")) {
5352
+ return firstLine + "...";
5353
+ }
5354
+ return firstLine;
5355
+ }
5356
+ function formatDate2(timestamp) {
5357
+ if (!timestamp) return "N/A";
5358
+ const d = new Date(timestamp);
5359
+ if (isNaN(d.getTime())) return "N/A";
5360
+ const pad = (n) => String(n).padStart(2, "0");
5361
+ const hh = pad(d.getHours());
5362
+ const min = pad(d.getMinutes());
5363
+ const sec = pad(d.getSeconds());
5364
+ return `${hh}:${min}:${sec}`;
5365
+ }
5366
+ var init_RevertModal = __esm({
5367
+ "src/components/RevertModal.jsx"() {
5368
+ init_terminal();
5369
+ }
5370
+ });
5371
+
5116
5372
  // src/utils/setup.js
5117
5373
  import puppeteer4 from "puppeteer";
5118
5374
  import { exec as exec3 } from "child_process";
5119
5375
  import { promisify } from "util";
5120
- import fs16 from "fs";
5376
+ import fs17 from "fs";
5121
5377
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
5122
5378
  var init_setup = __esm({
5123
5379
  "src/utils/setup.js"() {
@@ -5125,7 +5381,7 @@ var init_setup = __esm({
5125
5381
  checkPuppeteerReady = () => {
5126
5382
  try {
5127
5383
  const exePath = puppeteer4.executablePath();
5128
- const exists = exePath && fs16.existsSync(exePath);
5384
+ const exists = exePath && fs17.existsSync(exePath);
5129
5385
  if (exists) return true;
5130
5386
  } catch (e) {
5131
5387
  return false;
@@ -5156,28 +5412,28 @@ __export(app_exports, {
5156
5412
  default: () => App
5157
5413
  });
5158
5414
  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";
5415
+ import React11, { useState as useState8, useEffect as useEffect6, useRef as useRef2, useMemo } from "react";
5416
+ import { Box as Box11, Text as Text11, useInput as useInput5, useStdout } from "ink";
5161
5417
  import Spinner2 from "ink-spinner";
5162
- import fs17 from "fs-extra";
5163
- import path15 from "path";
5418
+ import fs18 from "fs-extra";
5419
+ import path16 from "path";
5164
5420
  import { exec as exec4 } from "child_process";
5165
5421
  import { fileURLToPath } from "url";
5166
5422
  import { MultilineInput } from "ink-multiline-input";
5167
5423
  import TextInput3 from "ink-text-input";
5168
5424
  import gradient from "gradient-string";
5169
5425
  function App({ args = [] }) {
5170
- const [confirmExit, setConfirmExit] = useState7(false);
5171
- const [exitCountdown, setExitCountdown] = useState7(10);
5426
+ const [confirmExit, setConfirmExit] = useState8(false);
5427
+ const [exitCountdown, setExitCountdown] = useState8(10);
5172
5428
  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({
5429
+ const [input, setInput] = useState8("");
5430
+ const [isExpanded, setIsExpanded] = useState8(false);
5431
+ const [mode, setMode] = useState8("Flux");
5432
+ const [terminalSize, setTerminalSize] = useState8({
5177
5433
  columns: stdout?.columns || 80,
5178
5434
  rows: stdout?.rows || 24
5179
5435
  });
5180
- const [selectedIndex, setSelectedIndex] = useState7(0);
5436
+ const [selectedIndex, setSelectedIndex] = useState8(0);
5181
5437
  const persistedModelRef = useRef2(null);
5182
5438
  const parsedArgs = useMemo(() => {
5183
5439
  const parsed = {};
@@ -5281,37 +5537,37 @@ function App({ args = [] }) {
5281
5537
  stdout.off("resize", handleResize);
5282
5538
  };
5283
5539
  }, [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);
5540
+ const [thinkingLevel, setThinkingLevel] = useState8("Medium");
5541
+ const [latestVer, setLatestVer] = useState8(null);
5542
+ const [showFullThinking, setShowFullThinking] = useState8(false);
5543
+ const [activeModel, setActiveModel] = useState8("gemma-4-31b-it");
5544
+ const [janitorModel, setJanitorModel] = useState8("gemma-4-26b-a4b-it");
5545
+ const [isInitializing, setIsInitializing] = useState8(true);
5546
+ const [apiKey, setApiKey] = useState8(null);
5547
+ const [tempKey, setTempKey] = useState8("");
5548
+ const [activeView, setActiveView] = useState8("chat");
5549
+ const [apiTier, setApiTier] = useState8("Free");
5550
+ const [quotas, setQuotas] = useState8({ agentLimit: 1500, backgroundLimit: 1500, searchLimit: 100, customModelId: "", customLimit: 0 });
5551
+ const [inputConfig, setInputConfig] = useState8(null);
5552
+ const [systemSettings, setSystemSettings] = useState8({ memory: true, compression: 0, autoExec: false, autoDeleteHistory: "7d", autoUpdate: false, updateManager: "npm", customUpdateCommand: "" });
5553
+ const [profileData, setProfileData] = useState8({ name: null, nickname: null, instructions: null });
5554
+ const [imageSettings, setImageSettings] = useState8({ keyType: "Default", quality: "Low-High", apiKey: "" });
5555
+ const [sessionStats, setSessionStats] = useState8({ tokens: 0 });
5556
+ const [sessionAgentCalls, setSessionAgentCalls] = useState8(0);
5557
+ const [sessionBackgroundCalls, setSessionBackgroundCalls] = useState8(0);
5558
+ const [sessionTotalTokens, setSessionTotalTokens] = useState8(0);
5559
+ const [sessionToolSuccess, setSessionToolSuccess] = useState8(0);
5560
+ const [sessionToolFailure, setSessionToolFailure] = useState8(0);
5561
+ const [sessionToolDenied, setSessionToolDenied] = useState8(0);
5562
+ const [sessionApiTime, setSessionApiTime] = useState8(0);
5563
+ const [sessionToolTime, setSessionToolTime] = useState8(0);
5564
+ const [sessionImageCount, setSessionImageCount] = useState8(0);
5565
+ const [sessionImageCredits, setSessionImageCredits] = useState8(0);
5566
+ const [dailyUsage, setDailyUsage] = useState8(null);
5567
+ const [chatId, setChatId] = useState8(generateChatId());
5568
+ const [activeCommand, setActiveCommand] = useState8(null);
5569
+ const [execOutput, setExecOutput] = useState8("");
5570
+ const [isTerminalFocused, setIsTerminalFocused] = useState8(false);
5315
5571
  useEffect6(() => {
5316
5572
  if (apiTier !== "Free" && activeModel === "gemma-4-31b-it") {
5317
5573
  setActiveModel("gemini-3-flash-preview");
@@ -5341,9 +5597,9 @@ function App({ args = [] }) {
5341
5597
  useEffect6(() => {
5342
5598
  execOutputRef.current = execOutput;
5343
5599
  }, [execOutput]);
5344
- const [autoAcceptWrites, setAutoAcceptWrites] = useState7(false);
5345
- const [pendingApproval, setPendingApproval] = useState7(null);
5346
- const [pendingAsk, setPendingAsk] = useState7(null);
5600
+ const [autoAcceptWrites, setAutoAcceptWrites] = useState8(false);
5601
+ const [pendingApproval, setPendingApproval] = useState8(null);
5602
+ const [pendingAsk, setPendingAsk] = useState8(null);
5347
5603
  const formatDuration = (totalSecs) => {
5348
5604
  const h = Math.floor(totalSecs / 3600);
5349
5605
  const m = Math.floor(totalSecs % 3600 / 60);
@@ -5358,15 +5614,18 @@ function App({ args = [] }) {
5358
5614
  if (ms < 1e3) return `${ms}ms`;
5359
5615
  return formatDuration(Math.floor(ms / 1e3));
5360
5616
  };
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(() => {
5617
+ const [statusText, setStatusText] = useState8(null);
5618
+ const [isSpinnerActive, setIsSpinnerActive] = useState8(true);
5619
+ const [isProcessing, setIsProcessing] = useState8(false);
5620
+ const [escPressed, setEscPressed] = useState8(false);
5621
+ const [escTimer, setEscTimer] = useState8(null);
5622
+ const [escPressCount, setEscPressCount] = useState8(0);
5623
+ const [recentPrompts, setRecentPrompts] = useState8([]);
5624
+ const escDoubleTimerRef = useRef2(null);
5625
+ const [queuedPrompt, setQueuedPrompt] = useState8(null);
5626
+ const [resolutionData, setResolutionData] = useState8(null);
5627
+ const [tempModelOverride, setTempModelOverride] = useState8(null);
5628
+ const [messages, setMessages] = useState8(() => {
5370
5629
  const logoMsg = { id: "logo-" + Date.now(), role: "system", text: FLUX_LOGO, isLogo: true, isMeta: true };
5371
5630
  const welcomeMsg = { id: "welcome", role: "system", text: "\u{1F30A}\u26A1 Welcome to Flux Flow! Type /help for commands.", isMeta: true };
5372
5631
  const isHomeDir = process.cwd() === os4.homedir();
@@ -5405,7 +5664,7 @@ function App({ args = [] }) {
5405
5664
  return msgs;
5406
5665
  });
5407
5666
  const queuedPromptRef = useRef2(null);
5408
- const [completedIndex, setCompletedIndex] = useState7(messages.length);
5667
+ const [completedIndex, setCompletedIndex] = useState8(messages.length);
5409
5668
  const windowedHistory = useMemo(() => {
5410
5669
  const MAX_HISTORY_LINES = 2e3;
5411
5670
  const width = terminalSize.columns || 80;
@@ -5440,7 +5699,7 @@ function App({ args = [] }) {
5440
5699
  return acc + Math.max(1, Math.ceil(line.length / wrapWidth));
5441
5700
  }, 0);
5442
5701
  const maxLines = Math.max(1, wrappedLinesCount);
5443
- useInput4((inputText, key) => {
5702
+ useInput5((inputText, key) => {
5444
5703
  if (key.tab && activeCommand) {
5445
5704
  setIsTerminalFocused((prev) => !prev);
5446
5705
  return;
@@ -5485,8 +5744,36 @@ function App({ args = [] }) {
5485
5744
  setEscPressed(false);
5486
5745
  if (escTimer) clearTimeout(escTimer);
5487
5746
  }
5488
- } else if (activeView !== "chat") {
5489
- setActiveView("chat");
5747
+ } else {
5748
+ if (activeView === "revert") {
5749
+ setActiveView("chat");
5750
+ setEscPressCount(0);
5751
+ } else if (activeView !== "chat") {
5752
+ setActiveView("chat");
5753
+ } else {
5754
+ setEscPressCount((prev) => {
5755
+ const nextCount = prev + 1;
5756
+ if (nextCount === 1) {
5757
+ if (escDoubleTimerRef.current) clearTimeout(escDoubleTimerRef.current);
5758
+ escDoubleTimerRef.current = setTimeout(() => setEscPressCount(0), 1e3);
5759
+ } else if (nextCount === 2) {
5760
+ if (escDoubleTimerRef.current) clearTimeout(escDoubleTimerRef.current);
5761
+ setEscPressCount(0);
5762
+ RevertManager.getChatHistory(chatId).then((prompts) => {
5763
+ if (prompts.length > 0) {
5764
+ setRecentPrompts(prompts.reverse());
5765
+ setActiveView("revert");
5766
+ } else {
5767
+ setMessages((prev2) => {
5768
+ setCompletedIndex(prev2.length + 1);
5769
+ return [...prev2, { id: "revert-empty-" + Date.now(), role: "system", text: "\u2139\uFE0F No revert checkpoints found for this session.", isMeta: true }];
5770
+ });
5771
+ }
5772
+ });
5773
+ }
5774
+ return nextCount;
5775
+ });
5776
+ }
5490
5777
  }
5491
5778
  }
5492
5779
  if (suggestions.length > 0 && activeView === "chat") {
@@ -5707,6 +5994,7 @@ function App({ args = [] }) {
5707
5994
  { cmd: "/help", desc: "Show all available commands" },
5708
5995
  { cmd: "/clear", desc: "Clear terminal screen" },
5709
5996
  { cmd: "/resume", desc: "Load previous session" },
5997
+ { cmd: "/revert", desc: "Revert codebase back to a checkpoint" },
5710
5998
  { cmd: "/save", desc: "Force save current chat" },
5711
5999
  { cmd: "/export", desc: "Export current chat in a .txt file" },
5712
6000
  { cmd: "/chats", desc: "List all chat sessions" },
@@ -5889,6 +6177,21 @@ ${hintText}`, color: "magenta" }];
5889
6177
  setIsExpanded(false);
5890
6178
  break;
5891
6179
  }
6180
+ case "/revert": {
6181
+ RevertManager.getChatHistory(chatId).then((prompts) => {
6182
+ if (prompts.length > 0) {
6183
+ setRecentPrompts(prompts.reverse());
6184
+ setActiveView("revert");
6185
+ } else {
6186
+ const s2 = emojiSpace(2);
6187
+ setMessages((prev) => {
6188
+ setCompletedIndex(prev.length + 1);
6189
+ return [...prev, { id: "revert-empty-" + Date.now(), role: "system", text: `No revert checkpoints found for this session.`, isMeta: true }];
6190
+ });
6191
+ }
6192
+ });
6193
+ break;
6194
+ }
5892
6195
  case "/mode": {
5893
6196
  if (parts[1]) {
5894
6197
  const newMode = parts[1].toLowerCase() === "flow" ? "Flow" : "Flux";
@@ -6124,7 +6427,7 @@ ${hintText}`, color: "magenta" }];
6124
6427
  }
6125
6428
  case "/export": {
6126
6429
  const exportFile = `export-fluxflow-${chatId}.txt`;
6127
- const exportPath = path15.join(process.cwd(), exportFile);
6430
+ const exportPath = path16.join(process.cwd(), exportFile);
6128
6431
  const exportLines = [];
6129
6432
  let insideAgentBlock = false;
6130
6433
  for (let i = 0; i < messages.length; i++) {
@@ -6175,7 +6478,7 @@ ${hintText}`, color: "magenta" }];
6175
6478
  }
6176
6479
  }
6177
6480
  const fileContent = exportLines.join("\n");
6178
- fs17.writeFileSync(exportPath, fileContent, "utf8");
6481
+ fs18.writeFileSync(exportPath, fileContent, "utf8");
6179
6482
  setMessages((prev) => {
6180
6483
  setCompletedIndex(prev.length + 1);
6181
6484
  return [...prev, {
@@ -6211,12 +6514,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
6211
6514
  setCompletedIndex(prev.length + 1);
6212
6515
  return [...prev, { id: Date.now(), role: "system", text: "\u2622\uFE0F [NUCLEAR] Initiating reset...", isMeta: true }];
6213
6516
  });
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);
6517
+ if (fs18.existsSync(LOGS_DIR)) fs18.removeSync(LOGS_DIR);
6518
+ if (fs18.existsSync(SECRET_DIR)) fs18.removeSync(SECRET_DIR);
6519
+ if (fs18.existsSync(SETTINGS_FILE)) fs18.removeSync(SETTINGS_FILE);
6217
6520
  try {
6218
- const items = fs17.readdirSync(FLUXFLOW_DIR);
6219
- if (items.length === 0) fs17.removeSync(FLUXFLOW_DIR);
6521
+ const items = fs18.readdirSync(FLUXFLOW_DIR);
6522
+ if (items.length === 0) fs18.removeSync(FLUXFLOW_DIR);
6220
6523
  } catch (e) {
6221
6524
  }
6222
6525
  setTimeout(() => {
@@ -6273,14 +6576,14 @@ ${list || "No saved chats found."}`, isMeta: true }];
6273
6576
  # SKILLS & WORKFLOWS
6274
6577
  - [Define custom step-by-step recipes for this project here]
6275
6578
  `;
6276
- const filePath = path15.join(process.cwd(), "FluxFlow.md");
6277
- if (fs17.pathExistsSync(filePath)) {
6579
+ const filePath = path16.join(process.cwd(), "FluxFlow.md");
6580
+ if (fs18.pathExistsSync(filePath)) {
6278
6581
  setMessages((prev) => {
6279
6582
  setCompletedIndex(prev.length + 1);
6280
6583
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "\u274C ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
6281
6584
  });
6282
6585
  } else {
6283
- fs17.writeFileSync(filePath, template);
6586
+ fs18.writeFileSync(filePath, template);
6284
6587
  setMessages((prev) => {
6285
6588
  setCompletedIndex(prev.length + 1);
6286
6589
  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 +7012,7 @@ Selection: ${val}`,
6709
7012
  const renderActiveView = () => {
6710
7013
  switch (activeView) {
6711
7014
  case "settings":
6712
- return /* @__PURE__ */ React10.createElement(
7015
+ return /* @__PURE__ */ React11.createElement(
6713
7016
  CommandMenu,
6714
7017
  {
6715
7018
  title: "System Settings",
@@ -6777,7 +7080,7 @@ Selection: ${val}`,
6777
7080
  }
6778
7081
  );
6779
7082
  case "apiTier":
6780
- return /* @__PURE__ */ React10.createElement(
7083
+ return /* @__PURE__ */ React11.createElement(
6781
7084
  CommandMenu,
6782
7085
  {
6783
7086
  title: `API Tier: ${apiTier}`,
@@ -6810,7 +7113,7 @@ Selection: ${val}`,
6810
7113
  }
6811
7114
  );
6812
7115
  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(
7116
+ 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
7117
  TextInput3,
6815
7118
  {
6816
7119
  value: inputConfig?.value || "",
@@ -6863,11 +7166,11 @@ Selection: ${val}`,
6863
7166
  }
6864
7167
  }
6865
7168
  }
6866
- )), /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
7169
+ )), /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", dimColor: true, italic: true }, "(Press Enter to confirm selection)")));
6867
7170
  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)"));
7171
+ 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
7172
  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(
7173
+ 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
7174
  CommandMenu,
6872
7175
  {
6873
7176
  title: "Confirm Intent",
@@ -6884,7 +7187,7 @@ Selection: ${val}`,
6884
7187
  }
6885
7188
  )));
6886
7189
  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(
7190
+ 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
7191
  CommandMenu,
6889
7192
  {
6890
7193
  title: "Confirm Intent",
@@ -6901,7 +7204,7 @@ Selection: ${val}`,
6901
7204
  }
6902
7205
  )));
6903
7206
  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(
7207
+ 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
7208
  CommandMenu,
6906
7209
  {
6907
7210
  title: "Final Confirmation",
@@ -6918,7 +7221,7 @@ Selection: ${val}`,
6918
7221
  }
6919
7222
  )));
6920
7223
  case "key":
6921
- return /* @__PURE__ */ React10.createElement(
7224
+ return /* @__PURE__ */ React11.createElement(
6922
7225
  CommandMenu,
6923
7226
  {
6924
7227
  title: "\u{1F511} API KEY MANAGEMENT",
@@ -6942,10 +7245,10 @@ Selection: ${val}`,
6942
7245
  }
6943
7246
  );
6944
7247
  case "deleteKey":
6945
- return /* @__PURE__ */ React10.createElement(Box10, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, (() => {
7248
+ return /* @__PURE__ */ React11.createElement(Box11, { flexDirection: "column", borderStyle: "round", borderColor: "red", paddingX: 2, paddingY: 1 }, (() => {
6946
7249
  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(
7250
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "red", bold: true }, "\u26D4", s, "DANGER: PURGE API KEY");
7251
+ })(), /* @__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
7252
  CommandMenu,
6950
7253
  {
6951
7254
  title: "Are you absolutely sure?",
@@ -6969,7 +7272,7 @@ Selection: ${val}`,
6969
7272
  case "exit":
6970
7273
  return null;
6971
7274
  case "ask":
6972
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%" }, /* @__PURE__ */ React10.createElement(
7275
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%" }, /* @__PURE__ */ React11.createElement(
6973
7276
  AskUserModal_default,
6974
7277
  {
6975
7278
  question: pendingAsk?.question,
@@ -6983,8 +7286,62 @@ Selection: ${val}`,
6983
7286
  }
6984
7287
  }
6985
7288
  ));
7289
+ case "revert":
7290
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
7291
+ RevertModal,
7292
+ {
7293
+ prompts: recentPrompts,
7294
+ onSelect: async (txId) => {
7295
+ try {
7296
+ const result = await RevertManager.rollbackToBefore(txId);
7297
+ if (result.success) {
7298
+ const { targetPrompt } = result;
7299
+ const targetIdx = messages.findIndex(
7300
+ (m) => m.role === "user" && m.text && (m.text.startsWith(targetPrompt) || m.text.includes(targetPrompt))
7301
+ );
7302
+ let newMsgs = [...messages];
7303
+ if (targetIdx !== -1) {
7304
+ newMsgs = messages.slice(0, targetIdx);
7305
+ }
7306
+ setMessages(newMsgs);
7307
+ setCompletedIndex(newMsgs.length);
7308
+ setInput(targetPrompt);
7309
+ setIsExpanded(targetPrompt.split("\n").length > 2);
7310
+ const historyToSave = newMsgs.filter((m) => !String(m.id).startsWith("welcome") && !m.isMeta);
7311
+ await saveChat(chatId, null, historyToSave);
7312
+ const s = emojiSpace(2);
7313
+ setMessages((prev) => {
7314
+ const finalMsgs = [...prev, {
7315
+ id: "revert-ok-" + Date.now(),
7316
+ role: "system",
7317
+ text: `\u{1F504}${s}[TIME TRAVEL] Codebase rolled back successfully! Reverted prompt loaded to input box.`,
7318
+ isMeta: true
7319
+ }];
7320
+ setCompletedIndex(finalMsgs.length);
7321
+ return finalMsgs;
7322
+ });
7323
+ setActiveView("chat");
7324
+ }
7325
+ } catch (err) {
7326
+ const s = emojiSpace(2);
7327
+ setMessages((prev) => {
7328
+ const finalMsgs = [...prev, {
7329
+ id: "revert-err-" + Date.now(),
7330
+ role: "system",
7331
+ text: `\u274C${s}[TIME TRAVEL ERROR] Failed to rollback: ${err.message}`,
7332
+ isMeta: true
7333
+ }];
7334
+ setCompletedIndex(finalMsgs.length);
7335
+ return finalMsgs;
7336
+ });
7337
+ setActiveView("chat");
7338
+ }
7339
+ },
7340
+ onClose: () => setActiveView("chat")
7341
+ }
7342
+ ));
6986
7343
  case "resume":
6987
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(
7344
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
6988
7345
  ResumeModal,
6989
7346
  {
6990
7347
  onSelect: async (id) => {
@@ -7014,9 +7371,9 @@ Selection: ${val}`,
7014
7371
  }
7015
7372
  ));
7016
7373
  case "memory":
7017
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
7374
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(MemoryModal, { onClose: () => setActiveView("chat") }));
7018
7375
  case "profile":
7019
- return /* @__PURE__ */ React10.createElement(
7376
+ return /* @__PURE__ */ React11.createElement(
7020
7377
  ProfileForm,
7021
7378
  {
7022
7379
  initialData: profileData,
@@ -7029,7 +7386,7 @@ Selection: ${val}`,
7029
7386
  }
7030
7387
  );
7031
7388
  case "resolution":
7032
- return /* @__PURE__ */ React10.createElement(Box10, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React10.createElement(
7389
+ return /* @__PURE__ */ React11.createElement(Box11, { width: "100%", alignItems: "center", justifyContent: "center" }, /* @__PURE__ */ React11.createElement(
7033
7390
  ResolutionModal,
7034
7391
  {
7035
7392
  data: resolutionData,
@@ -7048,15 +7405,15 @@ Selection: ${val}`,
7048
7405
  }
7049
7406
  ));
7050
7407
  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 ---"), (() => {
7408
+ 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
7409
  const args2 = parseArgs(pendingApproval?.args || "{}");
7053
7410
  const oldVal = args2.TargetContent || args2.content_to_replace || null;
7054
7411
  const newVal = args2.content || args2.ReplacementContent || args2.content_to_add || args2.replacementContent || null;
7055
7412
  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"))));
7413
+ 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
7414
  }
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(
7415
+ return /* @__PURE__ */ React11.createElement(Text11, { color: "white", wrap: "anywhere" }, newVal.replace(/\[\/n\]?/g, "\\n") || "Updating file content...");
7416
+ })()), /* @__PURE__ */ React11.createElement(Box11, { marginTop: 1 }, /* @__PURE__ */ React11.createElement(
7060
7417
  CommandMenu,
7061
7418
  {
7062
7419
  title: "Action Required",
@@ -7075,7 +7432,7 @@ Selection: ${val}`,
7075
7432
  }
7076
7433
  )));
7077
7434
  case "updateManager":
7078
- return /* @__PURE__ */ React10.createElement(
7435
+ return /* @__PURE__ */ React11.createElement(
7079
7436
  CommandMenu,
7080
7437
  {
7081
7438
  title: "Select Preferred Update Manager",
@@ -7112,7 +7469,7 @@ Selection: ${val}`,
7112
7469
  }
7113
7470
  );
7114
7471
  case "update":
7115
- return /* @__PURE__ */ React10.createElement(
7472
+ return /* @__PURE__ */ React11.createElement(
7116
7473
  UpdateProcessor_default,
7117
7474
  {
7118
7475
  latest: latestVer,
@@ -7138,7 +7495,7 @@ Selection: ${val}`,
7138
7495
  }
7139
7496
  );
7140
7497
  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(
7498
+ 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
7499
  CommandMenu,
7143
7500
  {
7144
7501
  title: "Risk Assessment Required",
@@ -7154,8 +7511,8 @@ Selection: ${val}`,
7154
7511
  }
7155
7512
  )));
7156
7513
  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,
7514
+ 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(
7515
+ Box11,
7159
7516
  {
7160
7517
  borderStyle: "round",
7161
7518
  borderColor: isProcessing ? "magenta" : "cyan",
@@ -7163,7 +7520,7 @@ Selection: ${val}`,
7163
7520
  paddingY: 0,
7164
7521
  width: "100%"
7165
7522
  },
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(
7523
+ /* @__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
7524
  MultilineInput,
7168
7525
  {
7169
7526
  value: "",
@@ -7180,7 +7537,7 @@ Selection: ${val}`,
7180
7537
  newline: (key) => key.return && key.shift || key.return && key.ctrl || key.return && key.leftAlt || key.return && key.rightAlt
7181
7538
  }
7182
7539
  }
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(
7540
+ )))) : /* @__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
7541
  MultilineInput,
7185
7542
  {
7186
7543
  focus: !isTerminalFocused,
@@ -7200,14 +7557,14 @@ Selection: ${val}`,
7200
7557
  ));
7201
7558
  }
7202
7559
  };
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(
7560
+ 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
7561
  ChatLayout_default,
7205
7562
  {
7206
7563
  messages: messages.slice(completedIndex),
7207
7564
  showFullThinking,
7208
7565
  columns: Math.max(20, (stdout?.columns || 80) - 1)
7209
7566
  }
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(
7567
+ ), 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
7568
  TextInput3,
7212
7569
  {
7213
7570
  value: tempKey,
@@ -7215,7 +7572,7 @@ Selection: ${val}`,
7215
7572
  onSubmit: handleSetup,
7216
7573
  mask: "*"
7217
7574
  }
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(
7575
+ ))), /* @__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
7576
  StatusBar_default,
7220
7577
  {
7221
7578
  mode,
@@ -7232,14 +7589,14 @@ Selection: ${val}`,
7232
7589
  const agentActiveMs = sessionApiTime + sessionToolTime;
7233
7590
  const apiPercent = agentActiveMs > 0 ? (sessionApiTime / agentActiveMs * 100).toFixed(1) : "0.0";
7234
7591
  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, "%)"))));
7592
+ 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
7593
  })(), suggestions.length > 0 && (() => {
7237
7594
  const windowSize = 5;
7238
7595
  const startIdx = Math.max(0, Math.min(selectedIndex - 2, suggestions.length - windowSize));
7239
7596
  const visible = suggestions.slice(startIdx, startIdx + windowSize);
7240
7597
  const remaining = suggestions.length - (startIdx + visible.length);
7241
- return /* @__PURE__ */ React10.createElement(
7242
- Box10,
7598
+ return /* @__PURE__ */ React11.createElement(
7599
+ Box11,
7243
7600
  {
7244
7601
  flexDirection: "column",
7245
7602
  borderStyle: "round",
@@ -7248,22 +7605,22 @@ Selection: ${val}`,
7248
7605
  paddingY: 0,
7249
7606
  width: "100%"
7250
7607
  },
7251
- /* @__PURE__ */ React10.createElement(Box10, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", bold: true, dimColor: true }, "\u{1F50D} COMMAND SUGGESTIONS")),
7608
+ /* @__PURE__ */ React11.createElement(Box11, { paddingX: 1, marginBottom: 0 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", bold: true, dimColor: true }, "\u{1F50D} COMMAND SUGGESTIONS")),
7252
7609
  visible.map((s, i) => {
7253
7610
  const actualIdx = startIdx + i;
7254
7611
  const isActive = actualIdx === selectedIndex;
7255
7612
  const isGemmaDisabled = s.cmd === "gemma-4-31b-it" && apiTier !== "Free";
7256
- return /* @__PURE__ */ React10.createElement(
7257
- Box10,
7613
+ return /* @__PURE__ */ React11.createElement(
7614
+ Box11,
7258
7615
  {
7259
7616
  key: s.cmd,
7260
7617
  flexDirection: "row",
7261
7618
  backgroundColor: isActive ? "#2a2a2a" : void 0,
7262
7619
  paddingX: 1
7263
7620
  },
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,
7621
+ /* @__PURE__ */ React11.createElement(Box11, { width: 3 }, /* @__PURE__ */ React11.createElement(Text11, { color: isActive ? "cyan" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
7622
+ /* @__PURE__ */ React11.createElement(Box11, { width: 32 }, /* @__PURE__ */ React11.createElement(
7623
+ Text11,
7267
7624
  {
7268
7625
  color: isGemmaDisabled ? "gray" : isActive ? "yellow" : "white",
7269
7626
  bold: isActive,
@@ -7271,10 +7628,10 @@ Selection: ${val}`,
7271
7628
  },
7272
7629
  s.cmd
7273
7630
  )),
7274
- /* @__PURE__ */ React10.createElement(Box10, { flexGrow: 1 }, /* @__PURE__ */ React10.createElement(Text10, { color: "gray", italic: true, dimColor: !isActive }, s.desc))
7631
+ /* @__PURE__ */ React11.createElement(Box11, { flexGrow: 1 }, /* @__PURE__ */ React11.createElement(Text11, { color: "gray", italic: true, dimColor: !isActive }, s.desc))
7275
7632
  );
7276
7633
  }),
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)"))
7634
+ 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
7635
  );
7279
7636
  })()));
7280
7637
  }
@@ -7293,6 +7650,8 @@ var init_app = __esm({
7293
7650
  init_ResumeModal();
7294
7651
  init_MemoryModal();
7295
7652
  init_UpdateProcessor();
7653
+ init_revert();
7654
+ init_RevertModal();
7296
7655
  init_usage();
7297
7656
  init_TerminalBox();
7298
7657
  init_arg_parser();
@@ -7303,11 +7662,11 @@ var init_app = __esm({
7303
7662
  init_text();
7304
7663
  SESSION_START_TIME = Date.now();
7305
7664
  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"));
7665
+ packageJsonPath = path16.join(path16.dirname(fileURLToPath(import.meta.url)), "../package.json");
7666
+ packageJson = JSON.parse(fs18.readFileSync(packageJsonPath, "utf8"));
7308
7667
  versionFluxflow = packageJson.version;
7309
7668
  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(
7669
+ 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
7670
  CommandMenu,
7312
7671
  {
7313
7672
  title: "Select Action",
@@ -7410,7 +7769,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
7410
7769
  ], { stdio: "inherit" });
7411
7770
  cp.on("exit", (code) => process.exit(code || 0));
7412
7771
  } else {
7413
- const { default: React11 } = await import("react");
7772
+ const { default: React12 } = await import("react");
7414
7773
  const { render } = await import("ink");
7415
7774
  const { default: App2 } = await Promise.resolve().then(() => (init_app(), app_exports));
7416
7775
  process.env.NODE_NO_WARNINGS = "1";
@@ -7433,5 +7792,5 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
7433
7792
  console.warn = (...args) => !isNoise(args) && originalWarn(...args);
7434
7793
  console.error = (...args) => !isNoise(args) && originalError(...args);
7435
7794
  process.stdout.write("\x1Bc");
7436
- render(/* @__PURE__ */ React11.createElement(App2, { args: process.argv.slice(2) }), { exitOnCtrlC: false });
7795
+ render(/* @__PURE__ */ React12.createElement(App2, { args: process.argv.slice(2) }), { exitOnCtrlC: false });
7437
7796
  }