fluxflow-cli 3.3.4 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/fluxflow.js CHANGED
@@ -189,6 +189,139 @@ var init_crypto = __esm({
189
189
  }
190
190
  });
191
191
 
192
+ // src/data/model_config.js
193
+ import fs3 from "fs";
194
+ import path3 from "path";
195
+ import { fileURLToPath } from "url";
196
+ var __filename, __dirname, packageConfigPath, pathsToCheck, userConfigPath, activeConfig, multimodalModelsSet, rebuildMultimodalSet, loadRemoteModelConfig, isModelMultimodal, getModels, getDefaultModel, getFallbackValue;
197
+ var init_model_config = __esm({
198
+ "src/data/model_config.js"() {
199
+ init_paths();
200
+ __filename = fileURLToPath(import.meta.url);
201
+ __dirname = path3.dirname(__filename);
202
+ packageConfigPath = "";
203
+ pathsToCheck = [
204
+ path3.join(__dirname, "../../model_config.json"),
205
+ // Dev: src/data/model_config.js -> root
206
+ path3.join(__dirname, "../model_config.json")
207
+ // Prod: dist/fluxflow.js -> root
208
+ ];
209
+ for (const p of pathsToCheck) {
210
+ try {
211
+ if (fs3.existsSync(p)) {
212
+ packageConfigPath = p;
213
+ break;
214
+ }
215
+ } catch (e) {
216
+ }
217
+ }
218
+ userConfigPath = path3.join(FLUXFLOW_DIR, "model_config.json");
219
+ activeConfig = null;
220
+ if (fs3.existsSync(userConfigPath)) {
221
+ try {
222
+ const fileContent = fs3.readFileSync(userConfigPath, "utf-8");
223
+ const parsed = JSON.parse(fileContent);
224
+ if (parsed && parsed.providers && parsed.fallbacks && parsed.release) {
225
+ activeConfig = parsed;
226
+ }
227
+ } catch (e) {
228
+ }
229
+ }
230
+ if (!activeConfig && packageConfigPath) {
231
+ try {
232
+ const fileContent = fs3.readFileSync(packageConfigPath, "utf-8");
233
+ const parsed = JSON.parse(fileContent);
234
+ if (parsed && parsed.providers && parsed.fallbacks && parsed.release) {
235
+ activeConfig = parsed;
236
+ }
237
+ } catch (e) {
238
+ }
239
+ }
240
+ if (!activeConfig) {
241
+ console.error("\n[Error] Unable to load model configuration. Please re-install the package from your package manager.\n");
242
+ process.exit(1);
243
+ }
244
+ multimodalModelsSet = /* @__PURE__ */ new Set();
245
+ rebuildMultimodalSet = () => {
246
+ const nextSet = /* @__PURE__ */ new Set();
247
+ if (activeConfig.providers) {
248
+ for (const providerKey of Object.keys(activeConfig.providers)) {
249
+ const provider = activeConfig.providers[providerKey];
250
+ if (provider && provider.models) {
251
+ const tiers = ["Free", "Paid"];
252
+ for (const tier of tiers) {
253
+ const list = provider.models[tier];
254
+ if (Array.isArray(list)) {
255
+ for (const m of list) {
256
+ if (m && m.cmd && m.multimodal === true) {
257
+ nextSet.add(m.cmd.trim().toLowerCase());
258
+ }
259
+ }
260
+ }
261
+ }
262
+ }
263
+ }
264
+ }
265
+ if (Array.isArray(activeConfig.multimodal_models)) {
266
+ for (const m of activeConfig.multimodal_models) {
267
+ if (m && typeof m === "string") {
268
+ nextSet.add(m.trim().toLowerCase());
269
+ }
270
+ }
271
+ }
272
+ multimodalModelsSet = nextSet;
273
+ };
274
+ rebuildMultimodalSet();
275
+ loadRemoteModelConfig = async () => {
276
+ try {
277
+ const url = "https://raw.githubusercontent.com/KushalRoyChowdhury/fluxflow-cli/main/src/data/model_config.json";
278
+ const res = await fetch(url, { signal: AbortSignal.timeout(3e3) });
279
+ if (res.ok) {
280
+ const data = await res.json();
281
+ if (data && data.providers && data.fallbacks && data.release) {
282
+ const isNewerVersion = typeof data.version === "number" && data.version > activeConfig.version;
283
+ const isNewerRelease = typeof data.release === "number" && data.release > activeConfig.release;
284
+ if (isNewerVersion || isNewerRelease) {
285
+ activeConfig = data;
286
+ rebuildMultimodalSet();
287
+ try {
288
+ if (!fs3.existsSync(FLUXFLOW_DIR)) {
289
+ fs3.mkdirSync(FLUXFLOW_DIR, { recursive: true });
290
+ }
291
+ fs3.writeFileSync(userConfigPath, JSON.stringify(data, null, 2), "utf-8");
292
+ } catch (writeErr) {
293
+ }
294
+ return true;
295
+ }
296
+ }
297
+ }
298
+ } catch (e) {
299
+ }
300
+ return false;
301
+ };
302
+ isModelMultimodal = (model) => {
303
+ if (!model) return false;
304
+ const lower = model.trim().toLowerCase();
305
+ if (multimodalModelsSet.has(lower)) return true;
306
+ if (lower.startsWith("gemini-") || lower.startsWith("gemma-")) return true;
307
+ return false;
308
+ };
309
+ getModels = (provider, apiTier) => {
310
+ const p = activeConfig.providers[provider];
311
+ if (!p) return [];
312
+ return p.models[apiTier === "Free" ? "Free" : "Paid"] || [];
313
+ };
314
+ getDefaultModel = (provider, apiTier) => {
315
+ const p = activeConfig.providers[provider];
316
+ if (!p) return "";
317
+ return apiTier === "Free" ? p.default_free : p.default_paid;
318
+ };
319
+ getFallbackValue = (key) => {
320
+ return activeConfig.fallbacks[key];
321
+ };
322
+ }
323
+ });
324
+
192
325
  // src/utils/secrets.js
193
326
  var secrets_exports = {};
194
327
  __export(secrets_exports, {
@@ -204,14 +337,14 @@ __export(secrets_exports, {
204
337
  saveSearchKey: () => saveSearchKey,
205
338
  saveSecret: () => saveSecret
206
339
  });
207
- import fs3 from "fs-extra";
208
- import path3 from "path";
340
+ import fs4 from "fs-extra";
341
+ import path4 from "path";
209
342
  var SECRET_FILE, getAPIKey, getProviderAPIKey, saveProviderAPIKey, getSecret, saveSecret, getSearchSecrets, saveAPIKey, saveSearchKey, saveSearchId, removeSecret, removeAPIKey;
210
343
  var init_secrets = __esm({
211
344
  "src/utils/secrets.js"() {
212
345
  init_crypto();
213
346
  init_paths();
214
- SECRET_FILE = path3.join(SECRET_DIR, "secrets.json");
347
+ SECRET_FILE = path4.join(SECRET_DIR, "secrets.json");
215
348
  getAPIKey = async () => {
216
349
  try {
217
350
  const secrets = readEncryptedJson(SECRET_FILE, {});
@@ -252,7 +385,7 @@ var init_secrets = __esm({
252
385
  }
253
386
  };
254
387
  saveSecret = async (key, value) => {
255
- await fs3.ensureDir(SECRET_DIR);
388
+ await fs4.ensureDir(SECRET_DIR);
256
389
  let current = readEncryptedJson(SECRET_FILE, {});
257
390
  current[key] = value;
258
391
  writeEncryptedJson(SECRET_FILE, current);
@@ -289,18 +422,19 @@ __export(settings_exports, {
289
422
  loadSettings: () => loadSettings,
290
423
  saveSettings: () => saveSettings
291
424
  });
292
- import fs4 from "fs-extra";
293
- import path4 from "path";
425
+ import fs5 from "fs-extra";
426
+ import path5 from "path";
294
427
  var DEFAULT_SETTINGS, loadSettings, migrateToExternal, saveSettings;
295
428
  var init_settings = __esm({
296
429
  "src/utils/settings.js"() {
297
430
  init_paths();
298
431
  init_crypto();
432
+ init_model_config();
299
433
  DEFAULT_SETTINGS = {
300
434
  mode: "Flux",
301
435
  thinkingLevel: "Medium",
302
436
  aiProvider: "Google",
303
- activeModel: "gemma-4-31b-it",
437
+ activeModel: getDefaultModel("Google", "Free") || "gemma-4-31b-it",
304
438
  showFullThinking: true,
305
439
  apiTier: "Free",
306
440
  quotas: {
@@ -343,7 +477,7 @@ var init_settings = __esm({
343
477
  loadSettings = async () => {
344
478
  let settingsObj = { ...DEFAULT_SETTINGS };
345
479
  try {
346
- if (await fs4.exists(SETTINGS_FILE)) {
480
+ if (await fs5.exists(SETTINGS_FILE)) {
347
481
  const saved = readAesEncryptedJson(SETTINGS_FILE);
348
482
  if (saved.imageSettings && saved.imageSettings.apiKey) {
349
483
  try {
@@ -395,12 +529,12 @@ var init_settings = __esm({
395
529
  const { FLUXFLOW_DIR: FLUXFLOW_DIR2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
396
530
  const folders = ["logs", "secret"];
397
531
  for (const folder of folders) {
398
- const src = path4.join(FLUXFLOW_DIR2, folder);
399
- const dest = path4.join(newPath, folder);
532
+ const src = path5.join(FLUXFLOW_DIR2, folder);
533
+ const dest = path5.join(newPath, folder);
400
534
  try {
401
- if (await fs4.exists(src)) {
402
- await fs4.ensureDir(dest);
403
- await fs4.copy(src, dest, { overwrite: true });
535
+ if (await fs5.exists(src)) {
536
+ await fs5.ensureDir(dest);
537
+ await fs5.copy(src, dest, { overwrite: true });
404
538
  }
405
539
  } catch (err) {
406
540
  console.error(`Migration failed for ${folder}:`, err);
@@ -426,7 +560,7 @@ var init_settings = __esm({
426
560
  if (updated.imageSettings) {
427
561
  updated.imageSettings = { ...updated.imageSettings, apiKey: "" };
428
562
  }
429
- await fs4.ensureDir(path4.dirname(SETTINGS_FILE));
563
+ await fs5.ensureDir(path5.dirname(SETTINGS_FILE));
430
564
  writeAesEncryptedJson(SETTINGS_FILE, updated);
431
565
  return true;
432
566
  } catch (err) {
@@ -4696,7 +4830,7 @@ var init_ChatLayout = __esm({
4696
4830
  }
4697
4831
  if (type === "agent-line") {
4698
4832
  if (!text || text.trim() === "") {
4699
- return null;
4833
+ return /* @__PURE__ */ React4.createElement(Box3, { height: 1 });
4700
4834
  }
4701
4835
  const animatedText = useStreamingText(text, isStreamingMsg, block.isActiveBlock);
4702
4836
  return /* @__PURE__ */ React4.createElement(Box3, { flexDirection: "column", paddingX: 1, width: "100%" }, /* @__PURE__ */ React4.createElement(CodeRenderer, { text: animatedText, columns }));
@@ -5197,7 +5331,7 @@ var init_main_tools = __esm({
5197
5331
  };
5198
5332
  TOOL_PROTOCOL = (mode, osDetected, isMultiModal, aiProvider, advanceRollback = false) => `
5199
5333
  -- TOOL DEFINITIONS --
5200
- Internal tools. **MUST use the EXACT syntax** [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED**
5334
+ Internal tools. **MUST use the EXACT syntax** [tool:functions.ToolName(args)]. **NO OTHER SYNTAX/MARKERS/BOUNDARY ALLOWED** Proper bracket balancing per schema is mandatory
5201
5335
 
5202
5336
  **TOOL USAGE POLICY:**
5203
5337
  - **MAX 3 TOOL CALLS PER TURN${mode === "Flux" ? " (EXCEPTION FOR Todo TOOL: 3+ CALLS ALLOWED, Run TOOL: Limit 1, OR 2 CONSECUTIVE Run TOOL)" : ""}. Next Turn, verify tool results, plan next**
@@ -6479,7 +6613,7 @@ var init_janitor_tools = __esm({
6479
6613
  Your tool syntax is: '[tool:functions.ToolName(args...)]'
6480
6614
 
6481
6615
  -- CHAT MANAGEMENT TOOLS (MUST CALL THESE 2 TOOLS ALWAYS) --
6482
- [tool:functions.Chat(title="<short creative title of FULL conversation in 3-5 words>")]. Consider full chat context to generate title NOT just latest message.
6616
+ [tool:functions.Chat(title="<short creative title of FULL conversation in 3 or 4 words>")]. Consider full chat context to generate title NOT just latest message.
6483
6617
  [tool:functions.Memory(action="temp", content="<summary of the user prompt & model responses ONLY FROM LATEST PROMPT UNDER 40 WORDS>. [Talked on: <date> <hour>]")]. Time format: YYYY-MM-DD HH am/pm
6484
6618
 
6485
6619
  ${isMemoryEnabled ? `-- User-specific long-term/permanent memory (USE BASED ON CONVERSATION CONTEXT, DO NOT RE-SAVE MEMORY WHICH IS ALREADY SAVED) --
@@ -6518,7 +6652,7 @@ var init_thinking_prompts = __esm({
6518
6652
  });
6519
6653
 
6520
6654
  // src/utils/prompts.js
6521
- import fs5 from "fs";
6655
+ import fs6 from "fs";
6522
6656
  var cachedProjectContextBlock, getMemoryPrompt, getSystemInstruction, getJanitorInstruction;
6523
6657
  var init_prompts = __esm({
6524
6658
  async "src/utils/prompts.js"() {
@@ -6594,7 +6728,7 @@ ${nicknameStr.length || userInstrStr.length ? "" : "\n"}` : "";
6594
6728
  { name: "architecture.md", desc: "System Structure" }
6595
6729
  ];
6596
6730
  if (isFirstPrompt || cachedProjectContextBlock === null) {
6597
- const foundFiles = projectContextFiles.filter((f) => fs5.existsSync(f.name));
6731
+ const foundFiles = projectContextFiles.filter((f) => fs6.existsSync(f.name));
6598
6732
  cachedProjectContextBlock = mode === "Flux" && foundFiles.length > 0 ? `
6599
6733
  -- PROJECT CONTEXT --
6600
6734
  ${foundFiles.map((f) => `- ${f.name}: ${f.desc}`).join("\n")}
@@ -6663,35 +6797,35 @@ Current date and Time: ${(/* @__PURE__ */ new Date()).toLocaleString([], { year:
6663
6797
  });
6664
6798
 
6665
6799
  // src/utils/revert.js
6666
- import fs6 from "fs-extra";
6667
- import path5 from "path";
6800
+ import fs7 from "fs-extra";
6801
+ import path6 from "path";
6668
6802
  async function performRestoration(change, tx) {
6669
6803
  try {
6670
6804
  if (change.type === "create") {
6671
- if (await fs6.pathExists(change.filePath)) {
6672
- await fs6.chmod(change.filePath, 438).catch(() => {
6805
+ if (await fs7.pathExists(change.filePath)) {
6806
+ await fs7.chmod(change.filePath, 438).catch(() => {
6673
6807
  });
6674
- await fs6.remove(change.filePath);
6808
+ await fs7.remove(change.filePath);
6675
6809
  }
6676
6810
  } else if (change.type === "update") {
6677
6811
  if (!change.backupFile) return;
6678
- const backupPath = path5.join(BACKUPS_DIR, tx.chatId, change.backupFile);
6679
- if (await fs6.pathExists(backupPath)) {
6812
+ const backupPath = path6.join(BACKUPS_DIR, tx.chatId, change.backupFile);
6813
+ if (await fs7.pathExists(backupPath)) {
6680
6814
  const backupContainer = readEncryptedJson(backupPath, null);
6681
6815
  if (!backupContainer || !backupContainer.data) {
6682
- throw new Error(`Backup container corrupt or empty for ${path5.basename(change.filePath)}`);
6816
+ throw new Error(`Backup container corrupt or empty for ${path6.basename(change.filePath)}`);
6683
6817
  }
6684
6818
  const decrypted = decryptAes(backupContainer.data);
6685
- if (await fs6.pathExists(change.filePath)) {
6686
- await fs6.chmod(change.filePath, 438).catch(() => {
6819
+ if (await fs7.pathExists(change.filePath)) {
6820
+ await fs7.chmod(change.filePath, 438).catch(() => {
6687
6821
  });
6688
6822
  }
6689
- await fs6.writeFile(change.filePath, decrypted, "utf8");
6823
+ await fs7.writeFile(change.filePath, decrypted, "utf8");
6690
6824
  } else {
6691
6825
  }
6692
6826
  }
6693
6827
  } catch (err) {
6694
- throw new Error(`Restoration failed for ${path5.basename(change.filePath)}: ${err.message}`);
6828
+ throw new Error(`Restoration failed for ${path6.basename(change.filePath)}: ${err.message}`);
6695
6829
  }
6696
6830
  }
6697
6831
  async function restoreWithRetry(change, tx, maxAttempts = 7) {
@@ -6716,7 +6850,7 @@ var init_revert = __esm({
6716
6850
  "src/utils/revert.js"() {
6717
6851
  init_paths();
6718
6852
  init_crypto();
6719
- fs6.ensureDirSync(BACKUPS_DIR);
6853
+ fs7.ensureDirSync(BACKUPS_DIR);
6720
6854
  currentTransaction = null;
6721
6855
  lastChatId = null;
6722
6856
  RevertManager = {
@@ -6741,16 +6875,16 @@ var init_revert = __esm({
6741
6875
  if (lastTx) {
6742
6876
  const alreadyBackedUp2 = lastTx.changes.some((c) => c.filePath === absolutePath);
6743
6877
  if (alreadyBackedUp2) return;
6744
- const fileExists2 = await fs6.pathExists(absolutePath);
6878
+ const fileExists2 = await fs7.pathExists(absolutePath);
6745
6879
  let type2 = fileExists2 || forcedContent ? "update" : "create";
6746
6880
  let backupFile2 = null;
6747
6881
  if (type2 === "update") {
6748
- const fileName = path5.basename(absolutePath);
6882
+ const fileName = path6.basename(absolutePath);
6749
6883
  backupFile2 = `${lastTx.id}_${fileName}.bak`;
6750
- const chatBackupDir = path5.join(BACKUPS_DIR, lastTx.chatId);
6751
- await fs6.ensureDir(chatBackupDir);
6752
- const backupPath = path5.join(chatBackupDir, backupFile2);
6753
- let content = forcedContent !== null ? forcedContent : await fs6.readFile(absolutePath, "utf8").catch(() => null);
6884
+ const chatBackupDir = path6.join(BACKUPS_DIR, lastTx.chatId);
6885
+ await fs7.ensureDir(chatBackupDir);
6886
+ const backupPath = path6.join(chatBackupDir, backupFile2);
6887
+ let content = forcedContent !== null ? forcedContent : await fs7.readFile(absolutePath, "utf8").catch(() => null);
6754
6888
  if (content !== null) {
6755
6889
  writeEncryptedJson(backupPath, { data: encryptAes(content) });
6756
6890
  } else {
@@ -6766,16 +6900,16 @@ var init_revert = __esm({
6766
6900
  }
6767
6901
  const alreadyBackedUp = currentTransaction.changes.some((c) => c.filePath === absolutePath);
6768
6902
  if (alreadyBackedUp) return;
6769
- const fileExists = await fs6.pathExists(absolutePath);
6903
+ const fileExists = await fs7.pathExists(absolutePath);
6770
6904
  let type = fileExists || forcedContent ? "update" : "create";
6771
6905
  let backupFile = null;
6772
6906
  if (type === "update") {
6773
- const fileName = path5.basename(absolutePath);
6907
+ const fileName = path6.basename(absolutePath);
6774
6908
  backupFile = `${currentTransaction.id}_${fileName}.bak`;
6775
- const chatBackupDir = path5.join(BACKUPS_DIR, currentTransaction.chatId);
6776
- await fs6.ensureDir(chatBackupDir);
6777
- const backupPath = path5.join(chatBackupDir, backupFile);
6778
- let content = forcedContent !== null ? forcedContent : await fs6.readFile(absolutePath, "utf8").catch(() => null);
6909
+ const chatBackupDir = path6.join(BACKUPS_DIR, currentTransaction.chatId);
6910
+ await fs7.ensureDir(chatBackupDir);
6911
+ const backupPath = path6.join(chatBackupDir, backupFile);
6912
+ let content = forcedContent !== null ? forcedContent : await fs7.readFile(absolutePath, "utf8").catch(() => null);
6779
6913
  if (content !== null) {
6780
6914
  writeEncryptedJson(backupPath, { data: encryptAes(content) });
6781
6915
  } else {
@@ -6798,14 +6932,14 @@ var init_revert = __esm({
6798
6932
  if (removed.changes) {
6799
6933
  for (const change of removed.changes) {
6800
6934
  if (change.backupFile) {
6801
- await fs6.remove(path5.join(BACKUPS_DIR, removed.chatId, change.backupFile)).catch(() => {
6935
+ await fs7.remove(path6.join(BACKUPS_DIR, removed.chatId, change.backupFile)).catch(() => {
6802
6936
  });
6803
6937
  }
6804
6938
  }
6805
6939
  }
6806
6940
  }
6807
6941
  writeEncryptedJson(LEDGER_FILE, ledger);
6808
- await fs6.remove(ACTIVE_TX_FILE).catch(() => {
6942
+ await fs7.remove(ACTIVE_TX_FILE).catch(() => {
6809
6943
  });
6810
6944
  } catch (err) {
6811
6945
  } finally {
@@ -6814,7 +6948,7 @@ var init_revert = __esm({
6814
6948
  },
6815
6949
  async recoverCrashedTransaction() {
6816
6950
  try {
6817
- if (await fs6.pathExists(ACTIVE_TX_FILE)) {
6951
+ if (await fs7.pathExists(ACTIVE_TX_FILE)) {
6818
6952
  const orphanedTx = readEncryptedJson(ACTIVE_TX_FILE, null);
6819
6953
  if (orphanedTx?.changes?.length > 0) {
6820
6954
  const ledger = readEncryptedJson(LEDGER_FILE, []);
@@ -6823,7 +6957,7 @@ var init_revert = __esm({
6823
6957
  writeEncryptedJson(LEDGER_FILE, ledger);
6824
6958
  }
6825
6959
  }
6826
- await fs6.remove(ACTIVE_TX_FILE).catch(() => {
6960
+ await fs7.remove(ACTIVE_TX_FILE).catch(() => {
6827
6961
  });
6828
6962
  }
6829
6963
  } catch (e) {
@@ -6843,8 +6977,8 @@ var init_revert = __esm({
6843
6977
  }
6844
6978
  for (const change of tx.changes) {
6845
6979
  if (change.backupFile) {
6846
- const backupPath = path5.join(BACKUPS_DIR, tx.chatId, change.backupFile);
6847
- await fs6.remove(backupPath).catch(() => {
6980
+ const backupPath = path6.join(BACKUPS_DIR, tx.chatId, change.backupFile);
6981
+ await fs7.remove(backupPath).catch(() => {
6848
6982
  });
6849
6983
  }
6850
6984
  }
@@ -6863,7 +6997,7 @@ var init_revert = __esm({
6863
6997
  },
6864
6998
  async deleteChatBackups(chatId) {
6865
6999
  try {
6866
- await fs6.remove(path5.join(BACKUPS_DIR, chatId));
7000
+ await fs7.remove(path6.join(BACKUPS_DIR, chatId));
6867
7001
  let ledger = readEncryptedJson(LEDGER_FILE, []);
6868
7002
  const clean = ledger.filter((t) => t.chatId !== chatId);
6869
7003
  if (ledger.length !== clean.length) writeEncryptedJson(LEDGER_FILE, clean);
@@ -6875,8 +7009,8 @@ var init_revert = __esm({
6875
7009
  });
6876
7010
 
6877
7011
  // src/utils/history.js
6878
- import fs7 from "fs-extra";
6879
- import path6 from "path";
7012
+ import fs8 from "fs-extra";
7013
+ import path7 from "path";
6880
7014
  import { nanoid } from "nanoid";
6881
7015
  var WRITE_LOCK, withLock, loadHistory, saveChat, saveChatTitle, deleteChat, generateChatId, cleanupOldHistory, parseCustomDate, cleanupLogFile, cleanupOldLogs, getTruncatedHistory, saveChatContext, loadChatContext;
6882
7016
  var init_history = __esm({
@@ -6900,9 +7034,9 @@ var init_history = __esm({
6900
7034
  return nextLock;
6901
7035
  };
6902
7036
  loadHistory = async () => {
6903
- await fs7.ensureDir(HISTORY_DIR);
7037
+ await fs8.ensureDir(HISTORY_DIR);
6904
7038
  let history = {};
6905
- if (await fs7.pathExists(HISTORY_FILE)) {
7039
+ if (await fs8.pathExists(HISTORY_FILE)) {
6906
7040
  try {
6907
7041
  history = readEncryptedJson(HISTORY_FILE, {});
6908
7042
  } catch (e) {
@@ -6910,10 +7044,10 @@ var init_history = __esm({
6910
7044
  }
6911
7045
  }
6912
7046
  for (const id in history) {
6913
- const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
7047
+ const chatFile = path7.join(HISTORY_DIR, `${id}.json`);
6914
7048
  Object.defineProperty(history[id], "messages", {
6915
7049
  get: () => {
6916
- if (fs7.existsSync(chatFile)) {
7050
+ if (fs8.existsSync(chatFile)) {
6917
7051
  try {
6918
7052
  return readEncryptedJson(chatFile, []);
6919
7053
  } catch (e) {
@@ -6936,7 +7070,7 @@ var init_history = __esm({
6936
7070
  };
6937
7071
  saveChat = async (id, name, messages) => {
6938
7072
  return withLock(async () => {
6939
- await fs7.ensureDir(HISTORY_DIR);
7073
+ await fs8.ensureDir(HISTORY_DIR);
6940
7074
  const history = await loadHistory();
6941
7075
  const existingChat = history[id];
6942
7076
  let persistentMessages = (messages || []).filter(
@@ -6950,7 +7084,7 @@ var init_history = __esm({
6950
7084
  } catch (e) {
6951
7085
  }
6952
7086
  const finalName = name || (existingChat ? existingChat.name : `Session ${id.slice(-6)}`);
6953
- const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
7087
+ const chatFile = path7.join(HISTORY_DIR, `${id}.json`);
6954
7088
  writeEncryptedJson(chatFile, persistentMessages);
6955
7089
  history[id] = {
6956
7090
  name: finalName,
@@ -6997,7 +7131,7 @@ var init_history = __esm({
6997
7131
  };
6998
7132
  }
6999
7133
  writeEncryptedJson(HISTORY_FILE, indexHistory);
7000
- if (await fs7.pathExists(CONTEXT_FILE)) {
7134
+ if (await fs8.pathExists(CONTEXT_FILE)) {
7001
7135
  try {
7002
7136
  const contextData = readEncryptedJson(CONTEXT_FILE, []);
7003
7137
  if (Array.isArray(contextData)) {
@@ -7018,10 +7152,10 @@ var init_history = __esm({
7018
7152
  writeEncryptedJson(TEMP_MEM_CHAT_FILE, cache);
7019
7153
  }
7020
7154
  await RevertManager.deleteChatBackups(id);
7021
- const chatFile = path6.join(HISTORY_DIR, `${id}.json`);
7022
- if (await fs7.pathExists(chatFile)) {
7155
+ const chatFile = path7.join(HISTORY_DIR, `${id}.json`);
7156
+ if (await fs8.pathExists(chatFile)) {
7023
7157
  try {
7024
- await fs7.remove(chatFile);
7158
+ await fs8.remove(chatFile);
7025
7159
  } catch (e) {
7026
7160
  }
7027
7161
  }
@@ -7094,8 +7228,8 @@ var init_history = __esm({
7094
7228
  };
7095
7229
  cleanupLogFile = async (filePath) => {
7096
7230
  try {
7097
- if (!await fs7.pathExists(filePath)) return;
7098
- const content = await fs7.readFile(filePath, "utf8");
7231
+ if (!await fs8.pathExists(filePath)) return;
7232
+ const content = await fs8.readFile(filePath, "utf8");
7099
7233
  if (!content.trim()) return;
7100
7234
  const lines = content.split("\n");
7101
7235
  const entries = [];
@@ -7135,26 +7269,26 @@ var init_history = __esm({
7135
7269
  }
7136
7270
  const finalContent = keptEntries.join("\n").trim();
7137
7271
  if (finalContent) {
7138
- await fs7.writeFile(filePath, finalContent + "\n", "utf8");
7272
+ await fs8.writeFile(filePath, finalContent + "\n", "utf8");
7139
7273
  } else {
7140
- await fs7.writeFile(filePath, "", "utf8");
7274
+ await fs8.writeFile(filePath, "", "utf8");
7141
7275
  }
7142
7276
  } catch (e) {
7143
7277
  }
7144
7278
  };
7145
7279
  cleanupOldLogs = async (logsDir) => {
7146
7280
  try {
7147
- if (!await fs7.pathExists(logsDir)) return;
7281
+ if (!await fs8.pathExists(logsDir)) return;
7148
7282
  const cleanRecursive = async (dir) => {
7149
- const files = await fs7.readdir(dir);
7283
+ const files = await fs8.readdir(dir);
7150
7284
  for (const file of files) {
7151
- const fullPath = path6.join(dir, file);
7152
- const stat = await fs7.stat(fullPath);
7285
+ const fullPath = path7.join(dir, file);
7286
+ const stat = await fs8.stat(fullPath);
7153
7287
  if (stat.isDirectory()) {
7154
7288
  await cleanRecursive(fullPath);
7155
- const subFiles = await fs7.readdir(fullPath);
7289
+ const subFiles = await fs8.readdir(fullPath);
7156
7290
  if (subFiles.length === 0) {
7157
- await fs7.remove(fullPath);
7291
+ await fs8.remove(fullPath);
7158
7292
  }
7159
7293
  } else if (file.endsWith(".log")) {
7160
7294
  await cleanupLogFile(fullPath);
@@ -7189,7 +7323,7 @@ var init_history = __esm({
7189
7323
  };
7190
7324
  loadChatContext = async (chatId) => {
7191
7325
  try {
7192
- if (!await fs7.pathExists(CONTEXT_FILE)) return { total: 0, context: 0 };
7326
+ if (!await fs8.pathExists(CONTEXT_FILE)) return { total: 0, context: 0 };
7193
7327
  const contextData = readEncryptedJson(CONTEXT_FILE, []);
7194
7328
  if (!Array.isArray(contextData)) return { total: 0, context: 0 };
7195
7329
  const entry = contextData.find((item) => Object.keys(item)[0] === String(chatId));
@@ -7202,8 +7336,8 @@ var init_history = __esm({
7202
7336
  });
7203
7337
 
7204
7338
  // src/utils/usage.js
7205
- import fs8 from "fs-extra";
7206
- import path7 from "path";
7339
+ import fs9 from "fs-extra";
7340
+ import path8 from "path";
7207
7341
  import os3 from "os";
7208
7342
  var getLocalBackupPath, BACKUP_FILE, generateSaveId, cachedUsage, writeTimeout, lastWriteTime, isDirty, defaultStats, purgeOldHistory, loadUsageFromFile, flushUsage, queueFlush, initUsage, forceFlushUsage, getDailyUsage, getMonthlyUsage, incrementUsage, runtimeSession, addToUsage, getCustomPeriodUsage, checkQuota, getImageQuotaBuckets, getImageQuotaLimit, checkImageQuota, getImageQuotaStats, recordImageGeneration;
7209
7343
  var init_usage = __esm({
@@ -7212,14 +7346,14 @@ var init_usage = __esm({
7212
7346
  init_crypto();
7213
7347
  getLocalBackupPath = () => {
7214
7348
  if (process.platform === "win32") {
7215
- const localAppData = process.env.LOCALAPPDATA || path7.join(os3.homedir(), "AppData", "Local");
7216
- return path7.join(localAppData, "FxFl", "backups", "backup.json");
7349
+ const localAppData = process.env.LOCALAPPDATA || path8.join(os3.homedir(), "AppData", "Local");
7350
+ return path8.join(localAppData, "FxFl", "backups", "backup.json");
7217
7351
  }
7218
7352
  if (process.platform === "darwin") {
7219
- return path7.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
7353
+ return path8.join(os3.homedir(), "Library", "Application Support", "FxFl", "backups", "backup.json");
7220
7354
  }
7221
- const xdgDataHome = process.env.XDG_DATA_HOME || path7.join(os3.homedir(), ".local", "share");
7222
- return path7.join(xdgDataHome, "fxfl", "backups", "backup.json");
7355
+ const xdgDataHome = process.env.XDG_DATA_HOME || path8.join(os3.homedir(), ".local", "share");
7356
+ return path8.join(xdgDataHome, "fxfl", "backups", "backup.json");
7223
7357
  };
7224
7358
  BACKUP_FILE = getLocalBackupPath();
7225
7359
  generateSaveId = () => Math.random().toString(36).substring(2) + Date.now().toString(36);
@@ -7261,8 +7395,8 @@ var init_usage = __esm({
7261
7395
  let primaryData = null;
7262
7396
  let backupData = null;
7263
7397
  try {
7264
- if (await fs8.exists(tempFile)) {
7265
- const rawContent = (await fs8.readFile(tempFile, "utf8")).trim();
7398
+ if (await fs9.exists(tempFile)) {
7399
+ const rawContent = (await fs9.readFile(tempFile, "utf8")).trim();
7266
7400
  let parsed = null;
7267
7401
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
7268
7402
  parsed = JSON.parse(rawContent);
@@ -7272,26 +7406,26 @@ var init_usage = __esm({
7272
7406
  if (parsed && parsed.date && parsed.stats) {
7273
7407
  primaryData = parsed;
7274
7408
  try {
7275
- await fs8.rename(tempFile, USAGE_FILE);
7409
+ await fs9.rename(tempFile, USAGE_FILE);
7276
7410
  } catch (e) {
7277
7411
  }
7278
7412
  } else {
7279
7413
  try {
7280
- await fs8.remove(tempFile);
7414
+ await fs9.remove(tempFile);
7281
7415
  } catch (e) {
7282
7416
  }
7283
7417
  }
7284
7418
  }
7285
7419
  } catch (err) {
7286
7420
  try {
7287
- await fs8.remove(tempFile);
7421
+ await fs9.remove(tempFile);
7288
7422
  } catch (e) {
7289
7423
  }
7290
7424
  }
7291
7425
  if (!primaryData) {
7292
7426
  try {
7293
- if (await fs8.exists(USAGE_FILE)) {
7294
- const rawContent = (await fs8.readFile(USAGE_FILE, "utf8")).trim();
7427
+ if (await fs9.exists(USAGE_FILE)) {
7428
+ const rawContent = (await fs9.readFile(USAGE_FILE, "utf8")).trim();
7295
7429
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
7296
7430
  primaryData = JSON.parse(rawContent);
7297
7431
  } else {
@@ -7302,8 +7436,8 @@ var init_usage = __esm({
7302
7436
  }
7303
7437
  }
7304
7438
  try {
7305
- if (await fs8.exists(BACKUP_FILE)) {
7306
- const rawContent = (await fs8.readFile(BACKUP_FILE, "utf8")).trim();
7439
+ if (await fs9.exists(BACKUP_FILE)) {
7440
+ const rawContent = (await fs9.readFile(BACKUP_FILE, "utf8")).trim();
7307
7441
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
7308
7442
  backupData = JSON.parse(rawContent);
7309
7443
  } else {
@@ -7317,8 +7451,8 @@ var init_usage = __esm({
7317
7451
  if (primaryData.saveId !== backupData.saveId) {
7318
7452
  resolvedData = primaryData;
7319
7453
  try {
7320
- await fs8.ensureDir(path7.dirname(BACKUP_FILE));
7321
- await fs8.copy(USAGE_FILE, BACKUP_FILE);
7454
+ await fs9.ensureDir(path8.dirname(BACKUP_FILE));
7455
+ await fs9.copy(USAGE_FILE, BACKUP_FILE);
7322
7456
  } catch (e) {
7323
7457
  }
7324
7458
  } else {
@@ -7327,15 +7461,15 @@ var init_usage = __esm({
7327
7461
  } else if (primaryData && !backupData) {
7328
7462
  resolvedData = primaryData;
7329
7463
  try {
7330
- await fs8.ensureDir(path7.dirname(BACKUP_FILE));
7331
- await fs8.copy(USAGE_FILE, BACKUP_FILE);
7464
+ await fs9.ensureDir(path8.dirname(BACKUP_FILE));
7465
+ await fs9.copy(USAGE_FILE, BACKUP_FILE);
7332
7466
  } catch (e) {
7333
7467
  }
7334
7468
  } else if (!primaryData && backupData) {
7335
7469
  resolvedData = backupData;
7336
7470
  try {
7337
- await fs8.ensureDir(path7.dirname(USAGE_FILE));
7338
- await fs8.copy(BACKUP_FILE, USAGE_FILE);
7471
+ await fs9.ensureDir(path8.dirname(USAGE_FILE));
7472
+ await fs9.copy(BACKUP_FILE, USAGE_FILE);
7339
7473
  } catch (e) {
7340
7474
  }
7341
7475
  }
@@ -7375,11 +7509,11 @@ var init_usage = __esm({
7375
7509
  flushUsage = async () => {
7376
7510
  if (!isDirty || !cachedUsage) return;
7377
7511
  try {
7378
- await fs8.ensureDir(path7.dirname(USAGE_FILE));
7512
+ await fs9.ensureDir(path8.dirname(USAGE_FILE));
7379
7513
  let diskData = null;
7380
7514
  try {
7381
- if (await fs8.exists(USAGE_FILE)) {
7382
- const rawContent = (await fs8.readFile(USAGE_FILE, "utf8")).trim();
7515
+ if (await fs9.exists(USAGE_FILE)) {
7516
+ const rawContent = (await fs9.readFile(USAGE_FILE, "utf8")).trim();
7383
7517
  if (rawContent.startsWith("{") || rawContent.startsWith("[")) {
7384
7518
  diskData = JSON.parse(rawContent);
7385
7519
  } else {
@@ -7455,14 +7589,14 @@ var init_usage = __esm({
7455
7589
  cachedUsage.saveId = generateSaveId();
7456
7590
  const tempFile = USAGE_FILE + ".tmp";
7457
7591
  const encryptedStr = encryptAes(JSON.stringify(cachedUsage, null, 2));
7458
- await fs8.writeFile(tempFile, encryptedStr, "utf8");
7459
- const fd = await fs8.open(tempFile, "r+");
7460
- await fs8.fsync(fd);
7461
- await fs8.close(fd);
7462
- await fs8.rename(tempFile, USAGE_FILE);
7592
+ await fs9.writeFile(tempFile, encryptedStr, "utf8");
7593
+ const fd = await fs9.open(tempFile, "r+");
7594
+ await fs9.fsync(fd);
7595
+ await fs9.close(fd);
7596
+ await fs9.rename(tempFile, USAGE_FILE);
7463
7597
  try {
7464
- await fs8.ensureDir(path7.dirname(BACKUP_FILE));
7465
- await fs8.copy(USAGE_FILE, BACKUP_FILE);
7598
+ await fs9.ensureDir(path8.dirname(BACKUP_FILE));
7599
+ await fs9.copy(USAGE_FILE, BACKUP_FILE);
7466
7600
  } catch (backupErr) {
7467
7601
  }
7468
7602
  isDirty = false;
@@ -7946,10 +8080,10 @@ var init_usage = __esm({
7946
8080
 
7947
8081
  // src/utils/puppeteer_helper.js
7948
8082
  import os4 from "os";
7949
- import path8 from "path";
7950
- import fs9 from "fs";
8083
+ import path9 from "path";
8084
+ import fs10 from "fs";
7951
8085
  import { createRequire } from "module";
7952
- import { fileURLToPath } from "url";
8086
+ import { fileURLToPath as fileURLToPath2 } from "url";
7953
8087
  function getPuppeteerConfig() {
7954
8088
  const platform = os4.platform();
7955
8089
  const arch = os4.arch();
@@ -7972,11 +8106,11 @@ function getPuppeteerConfig() {
7972
8106
  } else {
7973
8107
  return {};
7974
8108
  }
7975
- let configPath = path8.resolve(__dirname, "..", "..", ".puppeteerrc.cjs");
7976
- if (!fs9.existsSync(configPath)) {
7977
- configPath = path8.resolve(__dirname, "..", ".puppeteerrc.cjs");
8109
+ let configPath = path9.resolve(__dirname2, "..", "..", ".puppeteerrc.cjs");
8110
+ if (!fs10.existsSync(configPath)) {
8111
+ configPath = path9.resolve(__dirname2, "..", ".puppeteerrc.cjs");
7978
8112
  }
7979
- if (!fs9.existsSync(configPath)) {
8113
+ if (!fs10.existsSync(configPath)) {
7980
8114
  return {};
7981
8115
  }
7982
8116
  try {
@@ -7986,14 +8120,14 @@ function getPuppeteerConfig() {
7986
8120
  if (cacheDir) {
7987
8121
  process.env.PUPPETEER_CACHE_DIR = cacheDir;
7988
8122
  if (version) {
7989
- const expectedPath = path8.join(
8123
+ const expectedPath = path9.join(
7990
8124
  cacheDir,
7991
8125
  "chrome",
7992
8126
  `${pptrPlatform}-${version}`,
7993
8127
  subDir,
7994
8128
  execName
7995
8129
  );
7996
- if (fs9.existsSync(expectedPath)) {
8130
+ if (fs10.existsSync(expectedPath)) {
7997
8131
  return {
7998
8132
  executablePath: expectedPath,
7999
8133
  cacheDirectory: cacheDir
@@ -8001,15 +8135,15 @@ function getPuppeteerConfig() {
8001
8135
  }
8002
8136
  }
8003
8137
  const findExecutable = (dir) => {
8004
- if (!fs9.existsSync(dir)) return null;
8138
+ if (!fs10.existsSync(dir)) return null;
8005
8139
  try {
8006
- const files = fs9.readdirSync(dir);
8140
+ const files = fs10.readdirSync(dir);
8007
8141
  const dirsToSearch = [];
8008
8142
  for (const file of files) {
8009
- const fullPath = path8.join(dir, file);
8143
+ const fullPath = path9.join(dir, file);
8010
8144
  let stat;
8011
8145
  try {
8012
- stat = fs9.statSync(fullPath);
8146
+ stat = fs10.statSync(fullPath);
8013
8147
  } catch (e) {
8014
8148
  continue;
8015
8149
  }
@@ -8051,11 +8185,11 @@ function getPuppeteerConfig() {
8051
8185
  }
8052
8186
  return {};
8053
8187
  }
8054
- var require2, __dirname;
8188
+ var require2, __dirname2;
8055
8189
  var init_puppeteer_helper = __esm({
8056
8190
  "src/utils/puppeteer_helper.js"() {
8057
8191
  require2 = createRequire(import.meta.url);
8058
- __dirname = path8.dirname(fileURLToPath(import.meta.url));
8192
+ __dirname2 = path9.dirname(fileURLToPath2(import.meta.url));
8059
8193
  }
8060
8194
  });
8061
8195
 
@@ -8336,8 +8470,8 @@ var init_chat = __esm({
8336
8470
  });
8337
8471
 
8338
8472
  // src/tools/view_file.js
8339
- import fs10 from "fs";
8340
- import path9 from "path";
8473
+ import fs11 from "fs";
8474
+ import path10 from "path";
8341
8475
  var view_file;
8342
8476
  var init_view_file = __esm({
8343
8477
  "src/tools/view_file.js"() {
@@ -8349,16 +8483,16 @@ var init_view_file = __esm({
8349
8483
  const finalStart = sLine || 1;
8350
8484
  const finalEnd = eLine || (sLine ? sLine + 800 : 800);
8351
8485
  if (!targetPath) return 'ERROR: Missing "path" argument for view_file.';
8352
- const absolutePath = path9.resolve(process.cwd(), targetPath);
8486
+ const absolutePath = path10.resolve(process.cwd(), targetPath);
8353
8487
  try {
8354
- if (!fs10.existsSync(absolutePath)) {
8488
+ if (!fs11.existsSync(absolutePath)) {
8355
8489
  return `ERROR: File [${targetPath}] does not exist.`;
8356
8490
  }
8357
- const stats = fs10.statSync(absolutePath);
8491
+ const stats = fs11.statSync(absolutePath);
8358
8492
  if (stats.isDirectory()) {
8359
8493
  return `ERROR: Path [${targetPath}] is a directory. Use list_files instead.`;
8360
8494
  }
8361
- const ext = path9.extname(targetPath).toLowerCase();
8495
+ const ext = path10.extname(targetPath).toLowerCase();
8362
8496
  const videoExtensions = [".mp4", ".mkv", ".avi", ".mov", ".webm", ".flv", ".wmv", ".mpeg", ".mpg"];
8363
8497
  if (videoExtensions.includes(ext)) {
8364
8498
  const format = ext.slice(1).toUpperCase();
@@ -8378,7 +8512,7 @@ var init_view_file = __esm({
8378
8512
  if (!isMultiModal) {
8379
8513
  return `ERROR: Multimodality is not supported for the current model. Unable to load [${targetPath}].`;
8380
8514
  }
8381
- const buffer = fs10.readFileSync(absolutePath);
8515
+ const buffer = fs11.readFileSync(absolutePath);
8382
8516
  const base64 = buffer.toString("base64");
8383
8517
  const mimeType = mimeMap[ext];
8384
8518
  return {
@@ -8391,7 +8525,7 @@ var init_view_file = __esm({
8391
8525
  }
8392
8526
  };
8393
8527
  }
8394
- let content = fs10.readFileSync(absolutePath, "utf8");
8528
+ let content = fs11.readFileSync(absolutePath, "utf8");
8395
8529
  if (content.startsWith("\uFEFF")) {
8396
8530
  content = content.slice(1);
8397
8531
  }
@@ -8415,8 +8549,8 @@ ${code}`;
8415
8549
  });
8416
8550
 
8417
8551
  // src/tools/write_file.js
8418
- import fs11 from "fs";
8419
- import path10 from "path";
8552
+ import fs12 from "fs";
8553
+ import path11 from "path";
8420
8554
  var write_file;
8421
8555
  var init_write_file = __esm({
8422
8556
  "src/tools/write_file.js"() {
@@ -8427,14 +8561,14 @@ var init_write_file = __esm({
8427
8561
  if (!targetPath) return 'ERROR: Missing "path" argument for write_file.';
8428
8562
  if (content === void 0) return 'ERROR: Missing "content" argument for write_file.';
8429
8563
  content = content.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
8430
- const absolutePath = path10.resolve(process.cwd(), targetPath);
8431
- const parentDir = path10.dirname(absolutePath);
8564
+ const absolutePath = path11.resolve(process.cwd(), targetPath);
8565
+ const parentDir = path11.dirname(absolutePath);
8432
8566
  try {
8433
8567
  await RevertManager.recordFileChange(absolutePath);
8434
8568
  let ancestry = "";
8435
- if (fs11.existsSync(absolutePath)) {
8569
+ if (fs12.existsSync(absolutePath)) {
8436
8570
  try {
8437
- const oldData = fs11.readFileSync(absolutePath, "utf8");
8571
+ const oldData = fs12.readFileSync(absolutePath, "utf8");
8438
8572
  const lines = oldData.split(/\r?\n/);
8439
8573
  ancestry = `Old File contents:
8440
8574
  ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
@@ -8446,16 +8580,16 @@ ${lines.map((l, i) => `${i + 1} | ${l}`).join("\n")}
8446
8580
  `;
8447
8581
  }
8448
8582
  }
8449
- if (!fs11.existsSync(parentDir)) {
8450
- fs11.mkdirSync(parentDir, { recursive: true });
8583
+ if (!fs12.existsSync(parentDir)) {
8584
+ fs12.mkdirSync(parentDir, { recursive: true });
8451
8585
  }
8452
8586
  const strip = (t) => t.replace(/^```[\w]*\n?/, "").replace(/```\s*$/, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
8453
8587
  const processedContent = strip(content);
8454
8588
  const finalContent = processedContent.endsWith("\n") ? processedContent : processedContent + "\n";
8455
8589
  const lineCount = finalContent.split(/\r?\n/).length;
8456
8590
  const originalSize = Buffer.byteLength(finalContent, "utf8");
8457
- fs11.writeFileSync(absolutePath, finalContent, "utf8");
8458
- let verifiedContent = fs11.readFileSync(absolutePath, "utf8");
8591
+ fs12.writeFileSync(absolutePath, finalContent, "utf8");
8592
+ let verifiedContent = fs12.readFileSync(absolutePath, "utf8");
8459
8593
  const verifiedSize = Buffer.byteLength(verifiedContent, "utf8");
8460
8594
  const verifiedLines = verifiedContent.split(/\r?\n/);
8461
8595
  const verifiedLineCount = verifiedLines.length;
@@ -8490,8 +8624,8 @@ ${snippet}`;
8490
8624
  });
8491
8625
 
8492
8626
  // src/tools/update_file.js
8493
- import fs12 from "fs";
8494
- import path11 from "path";
8627
+ import fs13 from "fs";
8628
+ import path12 from "path";
8495
8629
  var update_file;
8496
8630
  var init_update_file = __esm({
8497
8631
  "src/tools/update_file.js"() {
@@ -8507,12 +8641,12 @@ var init_update_file = __esm({
8507
8641
  if (patchPairs.length === 0) {
8508
8642
  return "ERROR: No valid replacement pairs found. Use replaceContent1, newContent1, etc.";
8509
8643
  }
8510
- const absolutePath = path11.resolve(process.cwd(), targetPath);
8644
+ const absolutePath = path12.resolve(process.cwd(), targetPath);
8511
8645
  try {
8512
- if (!fs12.existsSync(absolutePath)) {
8646
+ if (!fs13.existsSync(absolutePath)) {
8513
8647
  return `ERROR: File [${targetPath}] does not exist. Use write_file instead.`;
8514
8648
  }
8515
- let diskContent = context.forcedContent || fs12.readFileSync(absolutePath, "utf8");
8649
+ let diskContent = context.forcedContent || fs13.readFileSync(absolutePath, "utf8");
8516
8650
  if (diskContent.startsWith("\uFEFF")) diskContent = diskContent.slice(1);
8517
8651
  const originalContent = diskContent.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
8518
8652
  const { content: finalContent, results } = applyPatches(originalContent, patchPairs);
@@ -8523,7 +8657,7 @@ var init_update_file = __esm({
8523
8657
  ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
8524
8658
  }
8525
8659
  await RevertManager.recordFileChange(absolutePath, originalContent);
8526
- fs12.writeFileSync(absolutePath, finalContent, "utf8");
8660
+ fs13.writeFileSync(absolutePath, finalContent, "utf8");
8527
8661
  const diffText = generateHighFidelityDiff(originalContent, finalContent, results, 12);
8528
8662
  if (failures.length > 0) {
8529
8663
  return `SUCCESS: File [${targetPath}] updated with some blocks failed. [${successes.length}/${patchPairs.length}] blocks applied.
@@ -8545,34 +8679,34 @@ ${diffText}`;
8545
8679
  });
8546
8680
 
8547
8681
  // src/tools/read_folder.js
8548
- import fs13 from "fs";
8549
- import path12 from "path";
8682
+ import fs14 from "fs";
8683
+ import path13 from "path";
8550
8684
  var read_folder;
8551
8685
  var init_read_folder = __esm({
8552
8686
  "src/tools/read_folder.js"() {
8553
8687
  init_arg_parser();
8554
8688
  read_folder = async (args) => {
8555
8689
  const { path: targetPath = "." } = parseArgs(args);
8556
- const absolutePath = path12.resolve(process.cwd(), targetPath);
8690
+ const absolutePath = path13.resolve(process.cwd(), targetPath);
8557
8691
  try {
8558
- if (!fs13.existsSync(absolutePath)) {
8692
+ if (!fs14.existsSync(absolutePath)) {
8559
8693
  return `ERROR: Path [${targetPath}] does not exist.`;
8560
8694
  }
8561
- const stats = fs13.statSync(absolutePath);
8695
+ const stats = fs14.statSync(absolutePath);
8562
8696
  if (!stats.isDirectory()) {
8563
8697
  return `ERROR: Path [${targetPath}] is a file, not a directory. Use view_file instead.`;
8564
8698
  }
8565
- const files = fs13.readdirSync(absolutePath);
8699
+ const files = fs14.readdirSync(absolutePath);
8566
8700
  const totalItems = files.length;
8567
8701
  const maxDisplay = 100;
8568
8702
  const displayItems = files.slice(0, maxDisplay);
8569
8703
  const folderData = [];
8570
8704
  for (const file of displayItems) {
8571
- const fPath = path12.join(absolutePath, file);
8705
+ const fPath = path13.join(absolutePath, file);
8572
8706
  let indicator = "\u{1F4C4}";
8573
8707
  let info = { name: file, type: "unknown", size: "N/A", mtime: "N/A" };
8574
8708
  try {
8575
- const fStats = fs13.statSync(fPath);
8709
+ const fStats = fs14.statSync(fPath);
8576
8710
  info = {
8577
8711
  name: file,
8578
8712
  type: fStats.isDirectory() ? "directory" : "file",
@@ -8657,8 +8791,8 @@ var init_ask_user = __esm({
8657
8791
 
8658
8792
  // src/tools/write_pdf.js
8659
8793
  import puppeteer3 from "puppeteer";
8660
- import path13 from "path";
8661
- import fs14 from "fs-extra";
8794
+ import path14 from "path";
8795
+ import fs15 from "fs-extra";
8662
8796
  import { PDFDocument } from "pdf-lib";
8663
8797
  var write_pdf;
8664
8798
  var init_write_pdf = __esm({
@@ -8675,10 +8809,10 @@ var init_write_pdf = __esm({
8675
8809
  } = parseArgs(args);
8676
8810
  if (!targetPath) return 'ERROR: Missing "path" argument for write_pdf.';
8677
8811
  if (!content) return 'ERROR: Missing "content" (HTML/CSS) for write_pdf.';
8678
- const absolutePath = path13.resolve(process.cwd(), targetPath);
8812
+ const absolutePath = path14.resolve(process.cwd(), targetPath);
8679
8813
  let browser = null;
8680
8814
  try {
8681
- await fs14.ensureDir(path13.dirname(absolutePath));
8815
+ await fs15.ensureDir(path14.dirname(absolutePath));
8682
8816
  await RevertManager.recordFileChange(absolutePath);
8683
8817
  const pptrConfig = getPuppeteerConfig();
8684
8818
  browser = await puppeteer3.launch({
@@ -8699,11 +8833,11 @@ var init_write_pdf = __esm({
8699
8833
  return null;
8700
8834
  }
8701
8835
  try {
8702
- const imgPath = path13.resolve(process.cwd(), originalSrc);
8703
- if (await fs14.pathExists(imgPath)) {
8704
- const ext = path13.extname(imgPath).toLowerCase().replace(".", "") || "png";
8836
+ const imgPath = path14.resolve(process.cwd(), originalSrc);
8837
+ if (await fs15.pathExists(imgPath)) {
8838
+ const ext = path14.extname(imgPath).toLowerCase().replace(".", "") || "png";
8705
8839
  const mime = ext === "jpg" ? "jpeg" : ext === "svg" ? "svg+xml" : ext;
8706
- const base64 = await fs14.readFile(imgPath, "base64");
8840
+ const base64 = await fs15.readFile(imgPath, "base64");
8707
8841
  return `data:image/${mime};base64,${base64}`;
8708
8842
  }
8709
8843
  } catch (e) {
@@ -8718,9 +8852,9 @@ var init_write_pdf = __esm({
8718
8852
  const fullTag = match[0];
8719
8853
  if (originalHref && fullTag.toLowerCase().includes("stylesheet") && !originalHref.startsWith("http://") && !originalHref.startsWith("https://") && !originalHref.startsWith("data:")) {
8720
8854
  try {
8721
- const cssPath = path13.resolve(process.cwd(), originalHref);
8722
- if (await fs14.pathExists(cssPath)) {
8723
- const cssContent = await fs14.readFile(cssPath, "utf-8");
8855
+ const cssPath = path14.resolve(process.cwd(), originalHref);
8856
+ if (await fs15.pathExists(cssPath)) {
8857
+ const cssContent = await fs15.readFile(cssPath, "utf-8");
8724
8858
  cssCache[fullTag] = `<style>${cssContent}</style>`;
8725
8859
  }
8726
8860
  } catch (e) {
@@ -8801,7 +8935,7 @@ var init_write_pdf = __esm({
8801
8935
  printBackground: true
8802
8936
  });
8803
8937
  const pdfDoc = await PDFDocument.load(pdfBytes);
8804
- const fileName = path13.basename(targetPath);
8938
+ const fileName = path14.basename(targetPath);
8805
8939
  pdfDoc.setTitle(`FluxFlow_${fileName}`);
8806
8940
  pdfDoc.setAuthor("FluxFlow CLI");
8807
8941
  pdfDoc.setSubject("Generated with Agentic AI System");
@@ -8809,8 +8943,8 @@ var init_write_pdf = __esm({
8809
8943
  pdfDoc.setCreator("FluxFlow PDF Engine");
8810
8944
  pdfDoc.setProducer("FluxFlow (Generative AI)");
8811
8945
  const finalPdfBytes = await pdfDoc.save();
8812
- await fs14.writeFile(absolutePath, finalPdfBytes);
8813
- const stats = await fs14.stat(absolutePath);
8946
+ await fs15.writeFile(absolutePath, finalPdfBytes);
8947
+ const stats = await fs15.stat(absolutePath);
8814
8948
  return `SUCCESS: PDF generated successfully at [${targetPath}] (${(stats.size / 1024).toFixed(2)} KB).`;
8815
8949
  } catch (err) {
8816
8950
  const errorMsg = err instanceof Error ? err.message : String(err);
@@ -8823,8 +8957,8 @@ var init_write_pdf = __esm({
8823
8957
  });
8824
8958
 
8825
8959
  // src/tools/write_docx.js
8826
- import fs15 from "fs-extra";
8827
- import path14 from "path";
8960
+ import fs16 from "fs-extra";
8961
+ import path15 from "path";
8828
8962
  import HTMLtoDOCX from "html-to-docx";
8829
8963
  var write_docx;
8830
8964
  var init_write_docx = __esm({
@@ -8838,11 +8972,11 @@ var init_write_docx = __esm({
8838
8972
  } = parseArgs(args);
8839
8973
  if (!targetPath) return 'ERROR: Missing "path" argument for write_docx.';
8840
8974
  if (!content) return 'ERROR: Missing "content" (HTML) for write_docx.';
8841
- const absolutePath = path14.resolve(process.cwd(), targetPath);
8975
+ const absolutePath = path15.resolve(process.cwd(), targetPath);
8842
8976
  try {
8843
- await fs15.ensureDir(path14.dirname(absolutePath));
8977
+ await fs16.ensureDir(path15.dirname(absolutePath));
8844
8978
  await RevertManager.recordFileChange(absolutePath);
8845
- const fileName = path14.basename(targetPath);
8979
+ const fileName = path15.basename(targetPath);
8846
8980
  const fullHtml = content.includes("<html") ? content : `
8847
8981
  <!DOCTYPE html>
8848
8982
  <html lang="en">
@@ -8863,7 +8997,7 @@ var init_write_docx = __esm({
8863
8997
  footer: true,
8864
8998
  pageNumber: true
8865
8999
  });
8866
- await fs15.writeFile(absolutePath, docxBuffer);
9000
+ await fs16.writeFile(absolutePath, docxBuffer);
8867
9001
  return `SUCCESS: Word document [${targetPath}] generated successfully.
8868
9002
  - Size: ${(docxBuffer.length / 1024).toFixed(1)} KB`;
8869
9003
  } catch (err) {
@@ -8875,21 +9009,21 @@ var init_write_docx = __esm({
8875
9009
  });
8876
9010
 
8877
9011
  // src/tools/search_keyword.js
8878
- import fs16 from "fs/promises";
8879
- import path15 from "path";
9012
+ import fs17 from "fs/promises";
9013
+ import path16 from "path";
8880
9014
  async function getFilesRecursively(dir, excludes, baseDir = dir, depth = 1) {
8881
9015
  if (depth > 12) return [];
8882
9016
  let results = [];
8883
9017
  let list;
8884
9018
  try {
8885
- list = await fs16.readdir(dir, { withFileTypes: true });
9019
+ list = await fs17.readdir(dir, { withFileTypes: true });
8886
9020
  } catch {
8887
9021
  return [];
8888
9022
  }
8889
9023
  for (const file of list) {
8890
- const fullPath = path15.join(dir, file.name);
8891
- const relativePath = path15.relative(baseDir, fullPath);
8892
- const pathSegments = relativePath.split(path15.sep).map((s) => s.toLowerCase());
9024
+ const fullPath = path16.join(dir, file.name);
9025
+ const relativePath = path16.relative(baseDir, fullPath);
9026
+ const pathSegments = relativePath.split(path16.sep).map((s) => s.toLowerCase());
8893
9027
  const isExcluded = excludes.some((ex) => pathSegments.includes(ex.toLowerCase()));
8894
9028
  if (isExcluded) continue;
8895
9029
  if (file.isDirectory()) {
@@ -8980,11 +9114,11 @@ var init_search_keyword = __esm({
8980
9114
  let filesToSearch = [];
8981
9115
  const rootDir = process.cwd();
8982
9116
  if (file) {
8983
- const fullPath = path15.resolve(rootDir, file);
9117
+ const fullPath = path16.resolve(rootDir, file);
8984
9118
  try {
8985
- const stat = await fs16.stat(fullPath);
9119
+ const stat = await fs17.stat(fullPath);
8986
9120
  if (stat.isFile()) {
8987
- filesToSearch.push({ fullPath, relativePath: path15.relative(rootDir, fullPath) });
9121
+ filesToSearch.push({ fullPath, relativePath: path16.relative(rootDir, fullPath) });
8988
9122
  }
8989
9123
  } catch {
8990
9124
  return `ERROR: File not found: ${file}`;
@@ -8994,7 +9128,7 @@ var init_search_keyword = __esm({
8994
9128
  }
8995
9129
  const searchPromises = filesToSearch.map(async (fileObj) => {
8996
9130
  try {
8997
- const content = await fs16.readFile(fileObj.fullPath, "utf-8");
9131
+ const content = await fs17.readFile(fileObj.fullPath, "utf-8");
8998
9132
  if (content.includes("\0")) return [];
8999
9133
  const lines = content.split(/\r?\n/);
9000
9134
  const fileMatches = [];
@@ -9052,8 +9186,8 @@ var init_search_keyword = __esm({
9052
9186
  });
9053
9187
 
9054
9188
  // src/tools/generate_image.js
9055
- import fs17 from "fs-extra";
9056
- import path16 from "path";
9189
+ import fs18 from "fs-extra";
9190
+ import path17 from "path";
9057
9191
  var injectPngMetadata, generate_image;
9058
9192
  var init_generate_image = __esm({
9059
9193
  "src/tools/generate_image.js"() {
@@ -9232,12 +9366,12 @@ var init_generate_image = __esm({
9232
9366
  "Seed": String(seed)
9233
9367
  };
9234
9368
  finalBuffer = injectPngMetadata(finalBuffer, metadata);
9235
- const absolutePath = path16.resolve(process.cwd(), outputPath);
9236
- await fs17.ensureDir(path16.dirname(absolutePath));
9369
+ const absolutePath = path17.resolve(process.cwd(), outputPath);
9370
+ await fs18.ensureDir(path17.dirname(absolutePath));
9237
9371
  await RevertManager.recordFileChange(absolutePath);
9238
- await fs17.writeFile(absolutePath, finalBuffer);
9372
+ await fs18.writeFile(absolutePath, finalBuffer);
9239
9373
  await recordImageGeneration(settings);
9240
- const ext = path16.extname(outputPath).toLowerCase();
9374
+ const ext = path17.extname(outputPath).toLowerCase();
9241
9375
  const mimeMap = {
9242
9376
  ".jpg": "image/jpeg",
9243
9377
  ".jpeg": "image/jpeg",
@@ -9352,13 +9486,13 @@ var init_addMemScore = __esm({
9352
9486
  });
9353
9487
 
9354
9488
  // src/utils/parsers.js
9355
- import fs18 from "fs-extra";
9356
- import path17 from "path";
9489
+ import fs19 from "fs-extra";
9490
+ import path18 from "path";
9357
9491
  import https from "https";
9358
9492
  async function downloadWasm(wasmFile, targetUrl = null) {
9359
9493
  const url = targetUrl || `https://unpkg.com/tree-sitter-wasms@0.1.13/out/${wasmFile}`;
9360
- const localPath = path17.join(PARSER_DIR, wasmFile);
9361
- await fs18.ensureDir(PARSER_DIR);
9494
+ const localPath = path18.join(PARSER_DIR, wasmFile);
9495
+ await fs19.ensureDir(PARSER_DIR);
9362
9496
  return new Promise((resolve, reject) => {
9363
9497
  const options = {
9364
9498
  headers: {
@@ -9379,27 +9513,27 @@ async function downloadWasm(wasmFile, targetUrl = null) {
9379
9513
  reject(new Error(`Failed to download ${wasmFile}: HTTP ${response.statusCode}`));
9380
9514
  return;
9381
9515
  }
9382
- const file = fs18.createWriteStream(localPath);
9516
+ const file = fs19.createWriteStream(localPath);
9383
9517
  response.pipe(file);
9384
9518
  file.on("finish", () => {
9385
9519
  file.close();
9386
9520
  resolve();
9387
9521
  });
9388
9522
  }).on("error", (err) => {
9389
- if (fs18.existsSync(localPath)) fs18.unlink(localPath, () => {
9523
+ if (fs19.existsSync(localPath)) fs19.unlink(localPath, () => {
9390
9524
  });
9391
9525
  reject(err);
9392
9526
  });
9393
9527
  });
9394
9528
  }
9395
9529
  function isParserInstalled(wasmFile) {
9396
- const localPath = path17.join(PARSER_DIR, wasmFile);
9397
- return fs18.existsSync(localPath);
9530
+ const localPath = path18.join(PARSER_DIR, wasmFile);
9531
+ return fs19.existsSync(localPath);
9398
9532
  }
9399
9533
  async function deleteParser(wasmFile) {
9400
- const localPath = path17.join(PARSER_DIR, wasmFile);
9401
- if (fs18.existsSync(localPath)) {
9402
- await fs18.unlink(localPath);
9534
+ const localPath = path18.join(PARSER_DIR, wasmFile);
9535
+ if (fs19.existsSync(localPath)) {
9536
+ await fs19.unlink(localPath);
9403
9537
  }
9404
9538
  }
9405
9539
  var EXTENSION_TO_WASM;
@@ -9421,8 +9555,8 @@ var init_parsers = __esm({
9421
9555
  });
9422
9556
 
9423
9557
  // src/tools/file_map.js
9424
- import fs19 from "fs-extra";
9425
- import path18 from "path";
9558
+ import fs20 from "fs-extra";
9559
+ import path19 from "path";
9426
9560
  import { createRequire as createRequire2 } from "module";
9427
9561
  function sanitize(text, limit = 50) {
9428
9562
  if (!text) return "";
@@ -9614,17 +9748,17 @@ var init_file_map = __esm({
9614
9748
  if (!filePath) {
9615
9749
  return 'ERROR: No file path provided. Use [tool:functions.FileMap(path="...")]';
9616
9750
  }
9617
- const absolutePath = path18.isAbsolute(filePath) ? filePath : path18.resolve(process.cwd(), filePath);
9618
- if (!fs19.existsSync(absolutePath)) {
9751
+ const absolutePath = path19.isAbsolute(filePath) ? filePath : path19.resolve(process.cwd(), filePath);
9752
+ if (!fs20.existsSync(absolutePath)) {
9619
9753
  return `ERROR: File not found: ${filePath}`;
9620
9754
  }
9621
- const ext = path18.extname(absolutePath).slice(1).toLowerCase();
9755
+ const ext = path19.extname(absolutePath).slice(1).toLowerCase();
9622
9756
  const wasmFile = EXTENSION_TO_WASM[ext];
9623
9757
  if (!wasmFile) {
9624
9758
  return `ERROR: Unsupported file extension: .${ext}`;
9625
9759
  }
9626
- const wasmPath = path18.resolve(PARSER_DIR, wasmFile);
9627
- if (!fs19.existsSync(wasmPath)) {
9760
+ const wasmPath = path19.resolve(PARSER_DIR, wasmFile);
9761
+ if (!fs20.existsSync(wasmPath)) {
9628
9762
  return `ERROR: Parser for .${ext} not found. Please download it in Settings > Other.`;
9629
9763
  }
9630
9764
  try {
@@ -9632,9 +9766,9 @@ var init_file_map = __esm({
9632
9766
  if (!isParserInitialized) {
9633
9767
  let tsWasmPath;
9634
9768
  try {
9635
- tsWasmPath = path18.join(path18.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
9769
+ tsWasmPath = path19.join(path19.dirname(require3.resolve("web-tree-sitter")), "tree-sitter.wasm");
9636
9770
  } catch (e) {
9637
- tsWasmPath = path18.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
9771
+ tsWasmPath = path19.join(process.cwd(), "node_modules", "web-tree-sitter", "tree-sitter.wasm");
9638
9772
  }
9639
9773
  await Parser.init({
9640
9774
  locateFile: (p) => {
@@ -9649,7 +9783,7 @@ var init_file_map = __esm({
9649
9783
  const parser = new Parser();
9650
9784
  const Lang = await TreeSitter.Language.load(wasmPath);
9651
9785
  parser.setLanguage(Lang);
9652
- const sourceCode = await fs19.readFile(absolutePath, "utf8");
9786
+ const sourceCode = await fs20.readFile(absolutePath, "utf8");
9653
9787
  const lines = sourceCode.split("\n").length;
9654
9788
  let maxDepth = 12;
9655
9789
  if (lines > 1e4) maxDepth = 2;
@@ -9672,8 +9806,8 @@ Stack: ${err.stack}` : "";
9672
9806
  });
9673
9807
 
9674
9808
  // src/tools/todo.js
9675
- import fs20 from "fs";
9676
- import path19 from "path";
9809
+ import fs21 from "fs";
9810
+ import path20 from "path";
9677
9811
  var todo;
9678
9812
  var init_todo = __esm({
9679
9813
  "src/tools/todo.js"() {
@@ -9684,8 +9818,8 @@ var init_todo = __esm({
9684
9818
  const { method, tasks, markDone } = parseArgs(args);
9685
9819
  const chatId = context.chatId || "default";
9686
9820
  if (!method) return 'ERROR: Missing "method" argument for todo tool (create/append/get).';
9687
- const todoDir = path19.join(DATA_DIR, "plan", chatId);
9688
- const todoFile = path19.join(todoDir, "todo.md");
9821
+ const todoDir = path20.join(DATA_DIR, "plan", chatId);
9822
+ const todoFile = path20.join(todoDir, "todo.md");
9689
9823
  const parseMessyArray = (input) => {
9690
9824
  if (!input || Array.isArray(input)) return input;
9691
9825
  const trimmed = String(input).trim();
@@ -9745,8 +9879,8 @@ var init_todo = __esm({
9745
9879
  };
9746
9880
  };
9747
9881
  try {
9748
- if (!fs20.existsSync(todoDir)) {
9749
- fs20.mkdirSync(todoDir, { recursive: true });
9882
+ if (!fs21.existsSync(todoDir)) {
9883
+ fs21.mkdirSync(todoDir, { recursive: true });
9750
9884
  }
9751
9885
  if (method === "create") {
9752
9886
  if (!tasks) return 'ERROR: Missing "tasks" for create method.';
@@ -9758,7 +9892,7 @@ var init_todo = __esm({
9758
9892
  markedCount = result.markedCount;
9759
9893
  }
9760
9894
  await RevertManager.recordFileChange(todoFile);
9761
- fs20.writeFileSync(todoFile, content, "utf8");
9895
+ fs21.writeFileSync(todoFile, content, "utf8");
9762
9896
  const total = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
9763
9897
  if (markedCount > 0) {
9764
9898
  const completed = content.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
@@ -9772,8 +9906,8 @@ ${content}`;
9772
9906
  if (!tasks) return 'ERROR: Missing "tasks" for append method.';
9773
9907
  const appendContent = getTasksString(tasks);
9774
9908
  await RevertManager.recordFileChange(todoFile);
9775
- fs20.appendFileSync(todoFile, appendContent, "utf8");
9776
- const fullContent = fs20.readFileSync(todoFile, "utf8");
9909
+ fs21.appendFileSync(todoFile, appendContent, "utf8");
9910
+ const fullContent = fs21.readFileSync(todoFile, "utf8");
9777
9911
  const lines = fullContent.split(/\r?\n/).map((l) => l.trim());
9778
9912
  const total = lines.filter((l) => l.startsWith("- [ ]") || l.startsWith("- [x]") || l.startsWith("- [X]")).length;
9779
9913
  const completed = lines.filter((l) => l.startsWith("- [x]") || l.startsWith("- [X]")).length;
@@ -9782,10 +9916,10 @@ ${content}`;
9782
9916
  ${fullContent}`;
9783
9917
  }
9784
9918
  if (method === "get") {
9785
- if (!fs20.existsSync(todoFile)) {
9919
+ if (!fs21.existsSync(todoFile)) {
9786
9920
  return "TODO GET: No task list found for this session.";
9787
9921
  }
9788
- let content = fs20.readFileSync(todoFile, "utf8");
9922
+ let content = fs21.readFileSync(todoFile, "utf8");
9789
9923
  let markedCount = 0;
9790
9924
  if (markDone) {
9791
9925
  const result = applyMarkDone(content, markDone);
@@ -9793,7 +9927,7 @@ ${fullContent}`;
9793
9927
  content = result.content;
9794
9928
  markedCount = result.markedCount;
9795
9929
  await RevertManager.recordFileChange(todoFile);
9796
- fs20.writeFileSync(todoFile, content, "utf8");
9930
+ fs21.writeFileSync(todoFile, content, "utf8");
9797
9931
  }
9798
9932
  }
9799
9933
  const totalLines = content.split(/\r?\n/).map((l) => l.trim());
@@ -10174,20 +10308,20 @@ var init_await = __esm({
10174
10308
  });
10175
10309
 
10176
10310
  // src/utils/advanceRevert.js
10177
- import fs21 from "fs-extra";
10178
- import path20 from "path";
10311
+ import fs22 from "fs-extra";
10312
+ import path21 from "path";
10179
10313
  async function scanWorkspace(dir, baseDir = dir) {
10180
10314
  const manifest = {};
10181
- const entries = await fs21.readdir(dir, { withFileTypes: true }).catch(() => []);
10315
+ const entries = await fs22.readdir(dir, { withFileTypes: true }).catch(() => []);
10182
10316
  for (const entry of entries) {
10183
10317
  if (JUNK_DIRECTORIES.includes(entry.name)) continue;
10184
- const fullPath = path20.join(dir, entry.name);
10185
- const relPath = path20.relative(baseDir, fullPath).replace(/\\/g, "/");
10318
+ const fullPath = path21.join(dir, entry.name);
10319
+ const relPath = path21.relative(baseDir, fullPath).replace(/\\/g, "/");
10186
10320
  if (entry.isDirectory()) {
10187
10321
  const sub = await scanWorkspace(fullPath, baseDir);
10188
10322
  Object.assign(manifest, sub);
10189
10323
  } else {
10190
- const stats = await fs21.stat(fullPath).catch(() => null);
10324
+ const stats = await fs22.stat(fullPath).catch(() => null);
10191
10325
  if (stats) {
10192
10326
  manifest[relPath] = {
10193
10327
  size: stats.size,
@@ -10199,34 +10333,34 @@ async function scanWorkspace(dir, baseDir = dir) {
10199
10333
  return manifest;
10200
10334
  }
10201
10335
  async function copyWorkspaceFiles(destDir, manifest) {
10202
- await fs21.ensureDir(destDir);
10336
+ await fs22.ensureDir(destDir);
10203
10337
  for (const relPath of Object.keys(manifest)) {
10204
- const srcPath = path20.join(process.cwd(), relPath);
10205
- const destPath = path20.join(destDir, relPath);
10206
- await fs21.ensureDir(path20.dirname(destPath));
10207
- await fs21.copyFile(srcPath, destPath).catch(() => {
10338
+ const srcPath = path21.join(process.cwd(), relPath);
10339
+ const destPath = path21.join(destDir, relPath);
10340
+ await fs22.ensureDir(path21.dirname(destPath));
10341
+ await fs22.copyFile(srcPath, destPath).catch(() => {
10208
10342
  });
10209
10343
  }
10210
10344
  }
10211
10345
  async function restoreSnapshotDir(srcDir, destDir, stats = null, baseDir = null) {
10212
- if (!await fs21.pathExists(srcDir)) return;
10346
+ if (!await fs22.pathExists(srcDir)) return;
10213
10347
  if (!baseDir) baseDir = srcDir;
10214
- const entries = await fs21.readdir(srcDir, { withFileTypes: true }).catch(() => []);
10348
+ const entries = await fs22.readdir(srcDir, { withFileTypes: true }).catch(() => []);
10215
10349
  for (const entry of entries) {
10216
- const srcPath = path20.join(srcDir, entry.name);
10217
- const destPath = path20.join(destDir, entry.name);
10350
+ const srcPath = path21.join(srcDir, entry.name);
10351
+ const destPath = path21.join(destDir, entry.name);
10218
10352
  if (entry.isDirectory()) {
10219
10353
  await restoreSnapshotDir(srcPath, destPath, stats, baseDir);
10220
10354
  } else {
10221
- const relPath = path20.relative(baseDir, srcPath).replace(/\\/g, "/");
10222
- const existed = await fs21.pathExists(destPath);
10355
+ const relPath = path21.relative(baseDir, srcPath).replace(/\\/g, "/");
10356
+ const existed = await fs22.pathExists(destPath);
10223
10357
  if (existed) {
10224
- await fs21.chmod(destPath, 438).catch(() => {
10358
+ await fs22.chmod(destPath, 438).catch(() => {
10225
10359
  });
10226
10360
  }
10227
- await fs21.ensureDir(path20.dirname(destPath));
10228
- const ok = await fs21.copyFile(srcPath, destPath).then(() => true).catch(() => false);
10229
- await fs21.chmod(destPath, 438).catch(() => {
10361
+ await fs22.ensureDir(path21.dirname(destPath));
10362
+ const ok = await fs22.copyFile(srcPath, destPath).then(() => true).catch(() => false);
10363
+ await fs22.chmod(destPath, 438).catch(() => {
10230
10364
  });
10231
10365
  if (stats) {
10232
10366
  if (!ok) {
@@ -10264,12 +10398,12 @@ var init_advanceRevert = __esm({
10264
10398
  AdvanceRevertManager = {
10265
10399
  async takeInitialSnapshot(chatId) {
10266
10400
  try {
10267
- const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10268
- await fs21.remove(snapshotsDir).catch(() => {
10401
+ const snapshotsDir = path21.join(DATA_DIR, "snapshots", chatId);
10402
+ await fs22.remove(snapshotsDir).catch(() => {
10269
10403
  });
10270
- await fs21.ensureDir(snapshotsDir);
10404
+ await fs22.ensureDir(snapshotsDir);
10271
10405
  const manifest = await scanWorkspace(process.cwd());
10272
- await copyWorkspaceFiles(path20.join(snapshotsDir, "initial"), manifest);
10406
+ await copyWorkspaceFiles(path21.join(snapshotsDir, "initial"), manifest);
10273
10407
  const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10274
10408
  ledger[chatId] = {
10275
10409
  initialManifest: manifest,
@@ -10318,7 +10452,7 @@ var init_advanceRevert = __esm({
10318
10452
  for (const file of changedFiles) {
10319
10453
  deltaManifest[file] = currentManifest[file];
10320
10454
  }
10321
- const turnDir = path20.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
10455
+ const turnDir = path21.join(DATA_DIR, "snapshots", chatId, `turn_${turnNumber}`);
10322
10456
  await copyWorkspaceFiles(turnDir, deltaManifest);
10323
10457
  }
10324
10458
  session.checkpoints.push({
@@ -10352,28 +10486,28 @@ var init_advanceRevert = __esm({
10352
10486
  const checkpoints = session.checkpoints || [];
10353
10487
  const targetIdx = checkpoints.findIndex((c) => c.id === checkpointId);
10354
10488
  if (targetIdx === -1) throw new Error(`Checkpoint [${checkpointId}] not found.`);
10355
- const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10489
+ const snapshotsDir = path21.join(DATA_DIR, "snapshots", chatId);
10356
10490
  const stats = { restored: 0, replaced: 0, failed: [] };
10357
10491
  const currentFiles = await scanWorkspace(process.cwd());
10358
10492
  for (const relPath of Object.keys(currentFiles)) {
10359
- const fullPath = path20.join(process.cwd(), relPath);
10360
- await fs21.chmod(fullPath, 438).catch(() => {
10493
+ const fullPath = path21.join(process.cwd(), relPath);
10494
+ await fs22.chmod(fullPath, 438).catch(() => {
10361
10495
  });
10362
- await fs21.remove(fullPath).catch(() => {
10496
+ await fs22.remove(fullPath).catch(() => {
10363
10497
  });
10364
10498
  }
10365
- const initialDir = path20.join(snapshotsDir, "initial");
10499
+ const initialDir = path21.join(snapshotsDir, "initial");
10366
10500
  await restoreSnapshotDir(initialDir, process.cwd(), stats, initialDir);
10367
10501
  for (let i = 1; i <= targetIdx; i++) {
10368
10502
  const cp = checkpoints[i];
10369
- const turnDir = path20.join(snapshotsDir, cp.id);
10503
+ const turnDir = path21.join(snapshotsDir, cp.id);
10370
10504
  await restoreSnapshotDir(turnDir, process.cwd(), stats, turnDir);
10371
10505
  if (cp.deletedFiles && cp.deletedFiles.length > 0) {
10372
10506
  for (const delFile of cp.deletedFiles) {
10373
- const fullPath = path20.join(process.cwd(), delFile);
10374
- await fs21.chmod(fullPath, 438).catch(() => {
10507
+ const fullPath = path21.join(process.cwd(), delFile);
10508
+ await fs22.chmod(fullPath, 438).catch(() => {
10375
10509
  });
10376
- await fs21.remove(fullPath).catch(() => {
10510
+ await fs22.remove(fullPath).catch(() => {
10377
10511
  });
10378
10512
  }
10379
10513
  }
@@ -10388,8 +10522,8 @@ var init_advanceRevert = __esm({
10388
10522
  },
10389
10523
  async cleanup(chatId) {
10390
10524
  try {
10391
- const snapshotsDir = path20.join(DATA_DIR, "snapshots", chatId);
10392
- await fs21.remove(snapshotsDir).catch(() => {
10525
+ const snapshotsDir = path21.join(DATA_DIR, "snapshots", chatId);
10526
+ await fs22.remove(snapshotsDir).catch(() => {
10393
10527
  });
10394
10528
  const ledger = readEncryptedJson(LEDGER_ADVANCE_FILE, {});
10395
10529
  if (ledger[chatId]) {
@@ -10743,9 +10877,9 @@ __export(ai_exports, {
10743
10877
  signalTermination: () => signalTermination
10744
10878
  });
10745
10879
  import { GoogleGenAI, ThinkingLevel, HarmBlockThreshold, HarmCategory } from "@google/genai";
10746
- import path21, { normalize } from "path";
10747
- import fs22 from "fs";
10748
- var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, MULTIMODAL_MODELS, isModelMultimodal, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10880
+ import path22, { normalize } from "path";
10881
+ import fs23 from "fs";
10882
+ var client, globalSettings, colorMainWords, withRetry, TERMINATION_SIGNAL, getCleanGroupedLength, stripAnsi2, fetchWithBackoff, getDeepSeekStream, getNVIDIAStream, wrapNvidiaStreamWithQueueDepth, getOpenRouterStream, signalTermination, isTerminationSignaled, TOOL_LABELS2, getToolDetail, runJanitorTask, getActiveToolContext, getContextSafeText, contextSafeReplace, getSanitizedText, translateKimiToolCalls, detectToolCalls, initAI, generateSimpleContent, consolidatePastMemories, compressHistory, deleteChatSummary, getAIStream, runSubagent;
10749
10883
  var init_ai = __esm({
10750
10884
  async "src/utils/ai.js"() {
10751
10885
  await init_prompts();
@@ -10759,6 +10893,7 @@ var init_ai = __esm({
10759
10893
  init_text();
10760
10894
  init_settings();
10761
10895
  init_subagent_state();
10896
+ init_model_config();
10762
10897
  init_paths();
10763
10898
  init_revert();
10764
10899
  init_advanceRevert();
@@ -10801,35 +10936,6 @@ var init_ai = __esm({
10801
10936
  }
10802
10937
  };
10803
10938
  TERMINATION_SIGNAL = false;
10804
- MULTIMODAL_MODELS = [
10805
- // OpenRouter models
10806
- "google/gemma-4-31b-it:free",
10807
- "moonshotai/kimi-k2.6:free",
10808
- "google/gemini-3.5-flash",
10809
- "qwen/qwen3.7-plus",
10810
- "minimax/minimax-m3",
10811
- "anthropic/claude-sonnet-4.5",
10812
- "anthropic/claude-opus-4.6",
10813
- "anthropic/claude-opus-4.8",
10814
- "openai/gpt-5.2-codex",
10815
- "openai/gpt-5.2-pro",
10816
- "openai/gpt-5.5-pro",
10817
- "moonshotai/kimi-k2.6",
10818
- // NVIDIA vision models
10819
- "moonshotai/kimi-k2.7",
10820
- "stepfun-ai/step-3.7-flash",
10821
- "google/gemma-4-31b-it",
10822
- "mistralai/mistral-medium-3.5-128b",
10823
- "qwen/qwen3.5-397b-a17b"
10824
- // Google models
10825
- // No need. All models on Gemini API is Multimodal
10826
- ];
10827
- isModelMultimodal = (model) => {
10828
- if (!model) return false;
10829
- const lower = model.toLowerCase();
10830
- if (lower.startsWith("gemini-") || lower.startsWith("gemma-")) return true;
10831
- return MULTIMODAL_MODELS.some((m) => m.toLowerCase() === lower);
10832
- };
10833
10939
  getCleanGroupedLength = (rawHistory) => {
10834
10940
  const preprocessed = rawHistory.filter(
10835
10941
  (m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !String(m.id).startsWith("welcome")
@@ -11139,6 +11245,7 @@ var init_ai = __esm({
11139
11245
  const isGPT = model.includes("gpt");
11140
11246
  const isQwen = model.includes("qwen");
11141
11247
  const isNemotron = model.includes("nemotron");
11248
+ const isLlama3 = model.includes("llama-3");
11142
11249
  const GPT_THINKING_LEVELS = {
11143
11250
  "Fast": "low",
11144
11251
  "Low": "low",
@@ -11157,7 +11264,8 @@ var init_ai = __esm({
11157
11264
  temperature,
11158
11265
  ...isGPT && { thinking: GPT_THINKING_LEVELS[thinkingLevel] || "high" }
11159
11266
  };
11160
- if (isKimi) {
11267
+ if (isLlama3) {
11268
+ } else if (isKimi) {
11161
11269
  body.chat_template_kwargs = { thinking: isThinking };
11162
11270
  } else if (isGemma) {
11163
11271
  body.chat_template_kwargs = { enable_thinking: isThinking };
@@ -11301,7 +11409,8 @@ var init_ai = __esm({
11301
11409
  resolve();
11302
11410
  }
11303
11411
  };
11304
- const cleanModelId = modelName.split("/").pop();
11412
+ let cleanModelId = modelName.split("/").pop();
11413
+ cleanModelId = cleanModelId.replace("llama-3.3", "llama-3_3");
11305
11414
  const pollUrl = `https://api.ngc.nvidia.com/v2/predict/queues/models/qc69jvmznzxy/${cleanModelId}`;
11306
11415
  let isStreamingStarted = false;
11307
11416
  let pollInterval = null;
@@ -11561,7 +11670,7 @@ var init_ai = __esm({
11561
11670
  return pArgs.id || pArgs.taskId;
11562
11671
  }
11563
11672
  const filePath = pArgs.path || pArgs.targetFile || pArgs.TargetFile || pArgs.directory;
11564
- return filePath ? path21.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
11673
+ return filePath ? path22.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/")) : null;
11565
11674
  } catch (e) {
11566
11675
  return null;
11567
11676
  }
@@ -11633,7 +11742,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11633
11742
  );
11634
11743
  const streamPromise = (async () => {
11635
11744
  if (aiProvider === "OpenRouter") {
11636
- const janitorOpenRouterModel = "google/gemma-4-26b-a4b-it:free";
11745
+ const janitorOpenRouterModel = getFallbackValue("janitor_open_router");
11637
11746
  const stream = getOpenRouterStream(
11638
11747
  apiKey,
11639
11748
  janitorOpenRouterModel,
@@ -11652,7 +11761,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11652
11761
  } else if (aiProvider === "DeepSeek") {
11653
11762
  const stream = getDeepSeekStream(
11654
11763
  apiKey,
11655
- "deepseek-chat",
11764
+ getFallbackValue("deepseek_fast_fallback"),
11656
11765
  janitorContents,
11657
11766
  janitorPrompt,
11658
11767
  "Fast",
@@ -11668,7 +11777,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11668
11777
  } else if (aiProvider === "NVIDIA") {
11669
11778
  const stream = getNVIDIAStream(
11670
11779
  apiKey,
11671
- "deepseek-ai/deepseek-v4-flash",
11780
+ getFallbackValue("nvidia_janitor_fallback"),
11672
11781
  janitorContents,
11673
11782
  janitorPrompt,
11674
11783
  "Fast",
@@ -11683,7 +11792,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11683
11792
  return { iterator: iterator2, firstResult: firstResult2 };
11684
11793
  } else {
11685
11794
  const stream = await client.models.generateContentStream({
11686
- model: janitorModel || (attempts === MAX_JANITOR_RETRIES ? "gemini-3.1-flash-lite" : "gemma-4-26b-a4b-it"),
11795
+ model: janitorModel || (attempts === MAX_JANITOR_RETRIES ? getFallbackValue("janitor_default") : getFallbackValue("gemma_janitor_fallback_google")),
11687
11796
  contents: janitorContents,
11688
11797
  config: {
11689
11798
  systemInstruction: janitorPrompt,
@@ -11729,7 +11838,7 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11729
11838
  const total = lastUsage.totalTokenCount || 0;
11730
11839
  const cached = lastUsage.cachedContentTokenCount || 0;
11731
11840
  const candidates = (lastUsage.candidatesTokenCount || 0) + (lastUsage.thoughtsTokenCount || 0);
11732
- const jModel = janitorModel || "gemini-3.1-flash-lite";
11841
+ const jModel = janitorModel || getFallbackValue("janitor_default");
11733
11842
  await addToUsage("tokens", total, aiProvider, jModel);
11734
11843
  if (cached > 0) {
11735
11844
  await addToUsage("cachedTokens", cached, aiProvider, jModel);
@@ -11802,9 +11911,9 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11802
11911
  }
11803
11912
  })() : String(err);
11804
11913
  await new Promise((resolve) => setTimeout(resolve, 1e3));
11805
- const janitorErrDir = path21.join(LOGS_DIR, "janitor");
11806
- if (!fs22.existsSync(janitorErrDir)) fs22.mkdirSync(janitorErrDir, { recursive: true });
11807
- fs22.appendFileSync(path21.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
11914
+ const janitorErrDir = path22.join(LOGS_DIR, "janitor");
11915
+ if (!fs23.existsSync(janitorErrDir)) fs23.mkdirSync(janitorErrDir, { recursive: true });
11916
+ fs23.appendFileSync(path22.join(janitorErrDir, "error.log"), `ERROR [Attempt ${attempts}/${MAX_JANITOR_RETRIES + 1}] [${date}]: ${errLog}
11808
11917
 
11809
11918
  `);
11810
11919
  if (attempts > MAX_JANITOR_RETRIES) break;
@@ -11813,8 +11922,8 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11813
11922
  }
11814
11923
  }
11815
11924
  if (attempts) {
11816
- const janitorErrDir = path21.join(LOGS_DIR, "janitor");
11817
- fs22.appendFileSync(path21.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
11925
+ const janitorErrDir = path22.join(LOGS_DIR, "janitor");
11926
+ fs23.appendFileSync(path22.join(janitorErrDir, "error.log"), `-----------------------------------------------------------------------------
11818
11927
 
11819
11928
  `);
11820
11929
  if (attempts >= MAX_JANITOR_RETRIES) {
@@ -11825,8 +11934,17 @@ ${originalTextProcessed.length > USER_CONTEXT_LENGTH ? "... (truncated) ...\n\n"
11825
11934
  }
11826
11935
  }
11827
11936
  if (process.stdout.isTTY) {
11828
- process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
11829
- process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow | Idle\x07");
11937
+ try {
11938
+ const historyIndex = await loadHistory();
11939
+ const chatData = historyIndex[chatId];
11940
+ const chatName = chatData?.name || "";
11941
+ const title = chatName && !chatName.startsWith("flow-") && !chatName.startsWith("Session ") ? chatName : "FluxFlow | Idle";
11942
+ process.stdout.write(`\x1B]0;${title}\x07`);
11943
+ process.stdout.write(`\x1B]633;P;TerminalTitle=${title}\x07`);
11944
+ } catch (e) {
11945
+ process.stdout.write("\x1B]0;FluxFlow | Idle\x07");
11946
+ process.stdout.write("\x1B]633;P;TerminalTitle=FluxFlow | Idle\x07");
11947
+ }
11830
11948
  }
11831
11949
  };
11832
11950
  getActiveToolContext = (text) => {
@@ -12301,10 +12419,10 @@ ${newMemoryListStr}
12301
12419
  let attempts = 0;
12302
12420
  const maxAttempts = 5;
12303
12421
  let success = false;
12304
- let targetModel = "gemma-4-26b-a4b-it";
12305
- if (aiProvider === "OpenRouter") targetModel = "google/gemma-4-26b-a4b-it:free";
12306
- if (aiProvider === "DeepSeek") targetModel = "deepseek-v4-flash";
12307
- if (aiProvider === "NVIDIA") targetModel = "deepseek-ai/deepseek-v4-flash";
12422
+ let targetModel = getFallbackValue("gemma_janitor_fallback_google");
12423
+ if (aiProvider === "OpenRouter") targetModel = getFallbackValue("janitor_open_router");
12424
+ if (aiProvider === "DeepSeek") targetModel = getFallbackValue("deepseek_level_1");
12425
+ if (aiProvider === "NVIDIA") targetModel = getFallbackValue("nvidia_janitor_fallback");
12308
12426
  while (attempts <= maxAttempts && !success) {
12309
12427
  attempts++;
12310
12428
  try {
@@ -12336,10 +12454,10 @@ ${newMemoryListStr}
12336
12454
  }
12337
12455
  })() : String(err);
12338
12456
  ;
12339
- const janitorLogDir = path21.join(LOGS_DIR, "janitor");
12340
- if (!fs22.existsSync(janitorLogDir)) fs22.mkdirSync(janitorLogDir, { recursive: true });
12341
- fs22.appendFileSync(
12342
- path21.join(janitorLogDir, "error.log"),
12457
+ const janitorLogDir = path22.join(LOGS_DIR, "janitor");
12458
+ if (!fs23.existsSync(janitorLogDir)) fs23.mkdirSync(janitorLogDir, { recursive: true });
12459
+ fs23.appendFileSync(
12460
+ path22.join(janitorLogDir, "error.log"),
12343
12461
  `[${(/* @__PURE__ */ new Date()).toLocaleString()}] Past memory batch consolidation error: ${errLog}
12344
12462
  `
12345
12463
  );
@@ -12347,7 +12465,7 @@ ${newMemoryListStr}
12347
12465
  };
12348
12466
  compressHistory = async (settings, history, isAuto = false) => {
12349
12467
  const { chatId, aiProvider = "Google" } = settings;
12350
- const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
12468
+ const summariesFile = path22.join(SECRET_DIR, "chat-summaries.json");
12351
12469
  const flattenContext = (hist) => {
12352
12470
  return hist.filter(
12353
12471
  (m) => (m.role === "user" || m.role === "agent" || m.role === "system") && m.role !== "think" && !m.isVisualFeedback && !m.isMeta && !String(m.id).startsWith("welcome")
@@ -12368,10 +12486,10 @@ Provide a new consolidated summary of the entire session.` : `Here is the conver
12368
12486
  ${flattenedText2}
12369
12487
 
12370
12488
  Provide a consolidated summary of the entire session.`;
12371
- let targetModel = "gemma-4-26b-a4b-it";
12372
- if (aiProvider === "OpenRouter") targetModel = "google/gemma-4-26b-a4b-it:free";
12373
- if (aiProvider === "DeepSeek") targetModel = "deepseek-v4-flash";
12374
- if (aiProvider === "NVIDIA") targetModel = "deepseek-ai/deepseek-v4-flash";
12489
+ let targetModel = getFallbackValue("gemma_janitor_fallback_google");
12490
+ if (aiProvider === "OpenRouter") targetModel = getFallbackValue("janitor_open_router");
12491
+ if (aiProvider === "DeepSeek") targetModel = getFallbackValue("deepseek_level_1");
12492
+ if (aiProvider === "NVIDIA") targetModel = getFallbackValue("nvidia_janitor_fallback");
12375
12493
  let attempts = 0;
12376
12494
  let success = false;
12377
12495
  let response = null;
@@ -12384,7 +12502,7 @@ Provide a consolidated summary of the entire session.`;
12384
12502
  if (attempts > 3) {
12385
12503
  if (aiProvider === "Google") {
12386
12504
  try {
12387
- const fallbackModel = "gemini-3.1-flash-lite";
12505
+ const fallbackModel = getFallbackValue("general_fallback");
12388
12506
  const fallback = await generateSimpleContent(settings, fallbackModel, prompt, systemInstruction, "Fast");
12389
12507
  return fallback.text || "";
12390
12508
  } catch (e) {
@@ -12421,8 +12539,8 @@ Provide a consolidated summary of the entire session.`;
12421
12539
  };
12422
12540
  deleteChatSummary = (chatId) => {
12423
12541
  try {
12424
- const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
12425
- if (fs22.existsSync(summariesFile)) {
12542
+ const summariesFile = path22.join(SECRET_DIR, "chat-summaries.json");
12543
+ if (fs23.existsSync(summariesFile)) {
12426
12544
  const summaries = readEncryptedJson(summariesFile, {});
12427
12545
  if (summaries[chatId]) {
12428
12546
  delete summaries[chatId];
@@ -12438,7 +12556,7 @@ Provide a consolidated summary of the entire session.`;
12438
12556
  if (!client && aiProvider === "Google") throw new Error("AI not initialized");
12439
12557
  const isMemoryEnabled = systemSettings?.memory !== false;
12440
12558
  const originalText = history[history.length - 1].text;
12441
- const summariesFile = path21.join(SECRET_DIR, "chat-summaries.json");
12559
+ const summariesFile = path22.join(SECRET_DIR, "chat-summaries.json");
12442
12560
  let wasCompressedInStream = false;
12443
12561
  const isFirstPrompt = history.filter((m) => m.role === "user").length === 1;
12444
12562
  const hasTitleSignal = originalText.includes("[TITLE-UPDATE]");
@@ -12682,7 +12800,7 @@ Provide a consolidated summary of the entire session.`;
12682
12800
  ];
12683
12801
  const safeReaddirWithTypes = (dir) => {
12684
12802
  try {
12685
- return fs22.readdirSync(dir, { withFileTypes: true });
12803
+ return fs23.readdirSync(dir, { withFileTypes: true });
12686
12804
  } catch (e) {
12687
12805
  return [];
12688
12806
  }
@@ -12695,16 +12813,16 @@ Provide a consolidated summary of the entire session.`;
12695
12813
  if (COLLAPSED_DIRS_GLOBAL.includes(entry.name)) continue;
12696
12814
  if (entry.isDirectory()) {
12697
12815
  currentCount.value++;
12698
- countFolders(path21.join(dir, entry.name), currentCount, depth + 1);
12816
+ countFolders(path22.join(dir, entry.name), currentCount, depth + 1);
12699
12817
  }
12700
12818
  }
12701
12819
  return currentCount.value;
12702
12820
  };
12703
12821
  const getDirTree = (dir, maxDepth, prefix = "", depth = 1) => {
12704
12822
  const entries = safeReaddirWithTypes(dir);
12705
- const sep = path21.sep;
12823
+ const sep = path22.sep;
12706
12824
  if (entries.length > 100) {
12707
- return `${prefix}\u2514\u2500\u2500 ${path21.basename(dir)}${sep} ...100+ files...
12825
+ return `${prefix}\u2514\u2500\u2500 ${path22.basename(dir)}${sep} ...100+ files...
12708
12826
  `;
12709
12827
  }
12710
12828
  let result = "";
@@ -12722,7 +12840,7 @@ Provide a consolidated summary of the entire session.`;
12722
12840
  ];
12723
12841
  finalItems.forEach((item, index) => {
12724
12842
  const isLast = index === finalItems.length - 1;
12725
- const filePath = path21.join(dir, item.name);
12843
+ const filePath = path22.join(dir, item.name);
12726
12844
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
12727
12845
  const childPrefix = prefix + (isLast ? " " : "\u2502 ");
12728
12846
  if (item.isCollapsed) {
@@ -12807,10 +12925,10 @@ ${currentSummary}
12807
12925
  if (isBridgeConnected()) {
12808
12926
  ideBlock = "[IDE CONTEXT]\n";
12809
12927
  if (ideCtx.file_focused !== "none") {
12810
- const relFocused = path21.relative(process.cwd(), ideCtx.file_focused);
12928
+ const relFocused = path22.relative(process.cwd(), ideCtx.file_focused);
12811
12929
  const relOpened = (ideCtx.opened_editors || []).map((p) => {
12812
- const rel = path21.relative(process.cwd(), p);
12813
- return rel.startsWith("..") ? `[External] ${path21.basename(p)}` : rel;
12930
+ const rel = path22.relative(process.cwd(), p);
12931
+ return rel.startsWith("..") ? `[External] ${path22.basename(p)}` : rel;
12814
12932
  });
12815
12933
  ideBlock += `Focused File: ${relFocused}
12816
12934
  Cursor Line: ${ideCtx.cursor_line}
@@ -12852,7 +12970,7 @@ Cursor Line: ${ideCtx.cursor_line}
12852
12970
  }
12853
12971
  const getSumForLimit = (limit, activeFiles2) => {
12854
12972
  return activeFiles2.reduce((sum, f) => {
12855
- const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path21.resolve(process.cwd(), f.path) === path21.resolve(ideCtx.file_focused));
12973
+ const isFocused = ideCtx.file_focused && (f.path === ideCtx.file_focused || path22.resolve(process.cwd(), f.path) === path22.resolve(ideCtx.file_focused));
12856
12974
  const fileLimit = isFocused ? Math.ceil(limit * 1.2) : limit;
12857
12975
  return sum + Math.min(f.edits.length, fileLimit);
12858
12976
  }, 0);
@@ -12886,7 +13004,7 @@ Cursor Line: ${ideCtx.cursor_line}
12886
13004
  }
12887
13005
  }
12888
13006
  for (const file of activeFiles) {
12889
- const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path21.resolve(process.cwd(), file.path) === path21.resolve(ideCtx.file_focused));
13007
+ const isFocused = ideCtx.file_focused && (file.path === ideCtx.file_focused || path22.resolve(process.cwd(), file.path) === path22.resolve(ideCtx.file_focused));
12890
13008
  const fileLimit = isFocused ? Math.ceil(chosenLimit * 1.2) : chosenLimit;
12891
13009
  if (file.edits.length > fileLimit) {
12892
13010
  file.edits = file.edits.slice(-fileLimit);
@@ -12971,9 +13089,9 @@ ${ideCtx.warnings}
12971
13089
  endLine = matchRange[2] ? parseInt(matchRange[2], 10) : startLine;
12972
13090
  filePath = tagClean.slice(0, matchRange.index);
12973
13091
  }
12974
- const absPath = path21.resolve(process.cwd(), filePath);
12975
- if (fs22.existsSync(absPath)) {
12976
- const stats = fs22.statSync(absPath);
13092
+ const absPath = path22.resolve(process.cwd(), filePath);
13093
+ if (fs23.existsSync(absPath)) {
13094
+ const stats = fs23.statSync(absPath);
12977
13095
  if (stats.isFile()) {
12978
13096
  const pathLower = filePath.toLowerCase();
12979
13097
  const isPdf = pathLower.endsWith(".pdf");
@@ -12982,7 +13100,7 @@ ${ideCtx.warnings}
12982
13100
  const isMultimodalFile = isImage || isPdf || isOfficeFile;
12983
13101
  const isSupported = aiProvider === "Google" || MULTIMODAL_MODELS.includes(modelName);
12984
13102
  if (isMultimodalFile && !isSupported) {
12985
- const label = `\u2718 Unsupported Modality: ${path21.basename(filePath)}`;
13103
+ const label = `\u2718 Unsupported Modality: ${path22.basename(filePath)}`;
12986
13104
  let terminalWidth = 115;
12987
13105
  if (process.stdout.isTTY) {
12988
13106
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -13033,7 +13151,7 @@ ${ideCtx.warnings}
13033
13151
  } else {
13034
13152
  let totalLines = "...";
13035
13153
  try {
13036
- const content = fs22.readFileSync(absPath, "utf8");
13154
+ const content = fs23.readFileSync(absPath, "utf8");
13037
13155
  totalLines = content.split("\n").length;
13038
13156
  } catch (e) {
13039
13157
  }
@@ -13149,6 +13267,7 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
13149
13267
  let accumulatedContext = "";
13150
13268
  let dedupeBuffer = "";
13151
13269
  let isDedupeActive = false;
13270
+ let detectedAnyToolCalls = false;
13152
13271
  let targetModel = modelName;
13153
13272
  let currentSystemInstruction = "";
13154
13273
  while (retryCount <= MAX_RETRIES && inStreamRetryCount <= MAX_RETRIES && !success && !TERMINATION_SIGNAL) {
@@ -13236,21 +13355,6 @@ ${activeSummaryBlock}${thinkingLevel !== "Fast" && thinkingLevel !== "xHigh" &&
13236
13355
  throw new Error("Error: Quota Exausted for Agent");
13237
13356
  }
13238
13357
  targetModel = modelName;
13239
- if (aiProvider === "DeepSeek" && thinkingLevel === "Fast" && targetModel.includes("flash")) {
13240
- targetModel = "deepseek-chat";
13241
- }
13242
- if (retryCount === MAX_RETRIES - 1) {
13243
- targetModel = aiProvider === "DeepSeek" ? "deepseek-v4-flash" : "gemini-3-flash-preview";
13244
- yield { type: "model_update", content: "Trying with fallback model" };
13245
- } else if (retryCount === MAX_RETRIES) {
13246
- targetModel = aiProvider === "DeepSeek" ? "deepseek-v4-pro" : "gemini-3.5-flash";
13247
- yield { type: "model_update", content: "Trying with fallback model" };
13248
- } else if (retryCount > 12 && retryCount < MAX_RETRIES - 2 && settings.apiKey !== "custom") {
13249
- targetModel = "gemma-4-31b-it";
13250
- yield { type: "model_update", content: "Trying with fallback Gemma Model" };
13251
- } else if (retryCount > 0) {
13252
- yield { type: "model_update", content: null };
13253
- }
13254
13358
  currentSystemInstruction = getSystemInstruction(profile, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? thinkingLevel : thinkingLevel, mode, systemSettings, isMemoryEnabled, isFirstPrompt, aiProvider, aiProvider === "Google" ? true : isMultiModal, !(targetModel || "gemma").toLowerCase().startsWith("gemma") ? true : false);
13255
13359
  const lastUserMsg = contents[contents.length - 1];
13256
13360
  if (isBridgeConnected() & loop > 0) {
@@ -13640,6 +13744,7 @@ ${ideErr} [/ERROR]`;
13640
13744
  }
13641
13745
  const toolContext = getActiveToolContext(turnText);
13642
13746
  if (toolContext.inside) {
13747
+ detectedAnyToolCalls = true;
13643
13748
  if (!lastToolEventTime) lastToolEventTime = Date.now();
13644
13749
  const NORMALIZE_MAP = {
13645
13750
  "Ask": "ask",
@@ -13683,7 +13788,7 @@ ${ideErr} [/ERROR]`;
13683
13788
  if (keyword) {
13684
13789
  detail = keyword.replace(/["']/g, "");
13685
13790
  } else if (filePath) {
13686
- detail = path21.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
13791
+ detail = path22.basename(filePath.replace(/["']/g, "").replace(/\\/g, "/"));
13687
13792
  } else if (title && (potentialTool === "invoke" || potentialTool === "invoke_sync")) {
13688
13793
  detail = title.replace(/["']/g, "").substring(0, 30);
13689
13794
  } else if (id && potentialTool === "get_progress") {
@@ -13712,7 +13817,7 @@ ${ideErr} [/ERROR]`;
13712
13817
  if (potentialTool === "invoke" || potentialTool === "invoke_sync" || potentialTool === "get_progress") {
13713
13818
  detail = val.substring(0, 30);
13714
13819
  } else {
13715
- detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path21.basename(val.replace(/\\/g, "/"));
13820
+ detail = potentialTool === "search_keyword" || potentialTool === "file_map" ? val : path22.basename(val.replace(/\\/g, "/"));
13716
13821
  }
13717
13822
  }
13718
13823
  }
@@ -13914,9 +14019,9 @@ ${ideErr} [/ERROR]`;
13914
14019
  let totalLines = "...";
13915
14020
  let actualEndLine = eLine;
13916
14021
  try {
13917
- const absPath = path21.resolve(process.cwd(), targetPath2);
13918
- if (fs22.existsSync(absPath)) {
13919
- const content = fs22.readFileSync(absPath, "utf8");
14022
+ const absPath = path22.resolve(process.cwd(), targetPath2);
14023
+ if (fs23.existsSync(absPath)) {
14024
+ const content = fs23.readFileSync(absPath, "utf8");
13920
14025
  const lines = content.split("\n").length;
13921
14026
  totalLines = lines;
13922
14027
  actualEndLine = Math.min(eLine, lines);
@@ -13936,8 +14041,8 @@ ${ideErr} [/ERROR]`;
13936
14041
  }
13937
14042
  } else if (normToolName === "list_files" || normToolName === "read_folder") {
13938
14043
  const action = normToolName === "list_files" ? "List" : "Browsed";
13939
- const path23 = parseArgs(toolCall.args).path;
13940
- label = `\u2714 ${action}: ${path23 === "." ? "./" : path23}`;
14044
+ const path24 = parseArgs(toolCall.args).path;
14045
+ label = `\u2714 ${action}: ${path24 === "." ? "./" : path24}`;
13941
14046
  } else if (normToolName === "write_file" || normToolName === "update_file") {
13942
14047
  const action = normToolName === "write_file" ? "Created" : "Edited";
13943
14048
  label = `\u2714 ${action}: ${parseArgs(toolCall.args).path || "..."}`;
@@ -14023,7 +14128,7 @@ ${ideErr} [/ERROR]`;
14023
14128
  const { command } = parseArgs(toolCall.args);
14024
14129
  if (command && settings.systemSettings && settings.systemSettings.allowExternalAccess === false) {
14025
14130
  const riskyPatterns = [/[a-zA-Z]:[\\\/]/i, /^\//, /\.\.[\\\/]/, /\/etc\//, /\/var\//, /\/root\//, /\/bin\//, /\/usr\//];
14026
- const currentDrive = path21.resolve(process.cwd()).substring(0, 3).toLowerCase();
14131
+ const currentDrive = path22.resolve(process.cwd()).substring(0, 3).toLowerCase();
14027
14132
  const splitCommands = (cmdString) => {
14028
14133
  const commands = [];
14029
14134
  let current = "";
@@ -14152,8 +14257,8 @@ ${ideErr} [/ERROR]`;
14152
14257
  const targetPath = parsedArgs.path || parsedArgs.targetPath || null;
14153
14258
  if (targetPath) {
14154
14259
  const isExternalOff = settings.systemSettings && settings.systemSettings.allowExternalAccess === false;
14155
- const absoluteTarget = path21.resolve(targetPath);
14156
- const absoluteCwd = path21.resolve(process.cwd());
14260
+ const absoluteTarget = path22.resolve(targetPath);
14261
+ const absoluteCwd = path22.resolve(process.cwd());
14157
14262
  if (isExternalOff && !absoluteTarget.startsWith(absoluteCwd)) {
14158
14263
  const denyMsg = `Access Denied. You are not allowed to access files outside the current workspace.`;
14159
14264
  if (normToolName === "write_file" || normToolName === "update_file") {
@@ -14342,7 +14447,7 @@ ${boxMid}`) };
14342
14447
  const toolArgs = parseArgs(toolCall.args);
14343
14448
  const { path: filePath } = toolArgs;
14344
14449
  if (filePath) {
14345
- const absPath = path21.resolve(process.cwd(), filePath);
14450
+ const absPath = path22.resolve(process.cwd(), filePath);
14346
14451
  const normalize2 = (p) => p ? p.toLowerCase().replace(/\\/g, "/").replace(/^[a-z]:/, (m) => m.toUpperCase()) : "";
14347
14452
  const normAbsPath = normalize2(absPath);
14348
14453
  let originalContent = "";
@@ -14352,8 +14457,8 @@ ${boxMid}`) };
14352
14457
  if (currentIDE && normFocused === normAbsPath && currentIDE.full_content) {
14353
14458
  originalContent = currentIDE.full_content;
14354
14459
  hasOriginal = true;
14355
- } else if (fs22.existsSync(absPath)) {
14356
- originalContent = fs22.readFileSync(absPath, "utf8");
14460
+ } else if (fs23.existsSync(absPath)) {
14461
+ originalContent = fs23.readFileSync(absPath, "utf8");
14357
14462
  hasOriginal = true;
14358
14463
  }
14359
14464
  originalContentForReporting = originalContent;
@@ -14380,9 +14485,9 @@ ${boxMid}`) };
14380
14485
  const successes = patchResults.filter((r) => r.success);
14381
14486
  const failures = patchResults.filter((r) => !r.success);
14382
14487
  if (successes.length === 0) {
14383
- const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path21.basename(absPath)}].
14488
+ const errorMsg = `[TOOL RESULT]: ERROR: Failed to apply patches to [${path22.basename(absPath)}].
14384
14489
  ${failures.map((f) => ` \u2022 ${f.error}`).join("\n")}`;
14385
- const errorLabel = `\u2714 Edited: ${path21.basename(absPath)}`.toUpperCase();
14490
+ const errorLabel = `\u2714 Edited: ${path22.basename(absPath)}`.toUpperCase();
14386
14491
  let terminalWidth = 115;
14387
14492
  if (process.stdout.isTTY) {
14388
14493
  terminalWidth = process.stdout.columns - 5 || 120;
@@ -14400,19 +14505,19 @@ ${boxMid}}`) };
14400
14505
  continue;
14401
14506
  }
14402
14507
  }
14403
- yield { type: "status", content: `Opening Diff in IDE: ${path21.basename(absPath)}` };
14508
+ yield { type: "status", content: `Opening Diff in IDE: ${path22.basename(absPath)}` };
14404
14509
  showDiffInIDE(absPath, originalContent, modifiedContent);
14405
14510
  diffOpened = true;
14406
14511
  await new Promise((r) => setTimeout(r, 50));
14407
14512
  } else if (normToolName === "write_file") {
14408
14513
  const rawContent = toolArgs.content || toolArgs.newContent || "";
14409
14514
  const modifiedContent = rawContent.endsWith("\n") ? rawContent : rawContent + "\n";
14410
- if (!fs22.existsSync(absPath)) {
14515
+ if (!fs23.existsSync(absPath)) {
14411
14516
  isNewFileCreated = true;
14412
- fs22.mkdirSync(path21.dirname(absPath), { recursive: true });
14413
- fs22.writeFileSync(absPath, "", "utf8");
14517
+ fs23.mkdirSync(path22.dirname(absPath), { recursive: true });
14518
+ fs23.writeFileSync(absPath, "", "utf8");
14414
14519
  }
14415
- yield { type: "status", content: `Opening New File Diff in IDE: ${path21.basename(absPath)}` };
14520
+ yield { type: "status", content: `Opening New File Diff in IDE: ${path22.basename(absPath)}` };
14416
14521
  showDiffInIDE(absPath, "", modifiedContent);
14417
14522
  diffOpened = true;
14418
14523
  await new Promise((r) => setTimeout(r, 50));
@@ -14448,11 +14553,11 @@ ${boxMid}}`) };
14448
14553
  if (normToolName === "write_file" || normToolName === "update_file") {
14449
14554
  const { path: filePath } = parseArgs(toolCall.args);
14450
14555
  if (filePath) {
14451
- const absPath = path21.resolve(process.cwd(), filePath);
14556
+ const absPath = path22.resolve(process.cwd(), filePath);
14452
14557
  closeDiffInIDE(absPath, approval);
14453
- if (approval === "deny" && isNewFileCreated && fs22.existsSync(absPath)) {
14558
+ if (approval === "deny" && isNewFileCreated && fs23.existsSync(absPath)) {
14454
14559
  try {
14455
- fs22.unlinkSync(absPath);
14560
+ fs23.unlinkSync(absPath);
14456
14561
  } catch (e) {
14457
14562
  }
14458
14563
  }
@@ -14464,13 +14569,13 @@ ${boxMid}}`) };
14464
14569
  }
14465
14570
  if (approval === "allow" && diffOpened && isBridgeConnected()) {
14466
14571
  const { path: filePath } = parseArgs(toolCall.args);
14467
- const absPath = path21.resolve(process.cwd(), filePath);
14572
+ const absPath = path22.resolve(process.cwd(), filePath);
14468
14573
  const finalIDE = await getIDEContext();
14469
14574
  let finalContent = "";
14470
14575
  if (finalIDE && finalIDE.file_focused === absPath && finalIDE.full_content) {
14471
14576
  finalContent = finalIDE.full_content;
14472
- } else if (fs22.existsSync(absPath)) {
14473
- finalContent = fs22.readFileSync(absPath, "utf8");
14577
+ } else if (fs23.existsSync(absPath)) {
14578
+ finalContent = fs23.readFileSync(absPath, "utf8");
14474
14579
  }
14475
14580
  const verifiedLines = finalContent.split(/\r?\n/);
14476
14581
  const verifiedLineCount = verifiedLines.length;
@@ -14638,7 +14743,7 @@ ${boxMid}`) };
14638
14743
  try {
14639
14744
  const { path: filePath } = parseArgs(toolCall.args);
14640
14745
  if (filePath) {
14641
- const absPath = path21.resolve(process.cwd(), filePath);
14746
+ const absPath = path22.resolve(process.cwd(), filePath);
14642
14747
  const currentIDE = await getIDEContext();
14643
14748
  if (currentIDE && currentIDE.file_focused === absPath && currentIDE.full_content) {
14644
14749
  execToolContext.forcedContent = currentIDE.full_content;
@@ -14653,7 +14758,7 @@ ${boxMid}`) };
14653
14758
  if ((normToolName === "write_file" || normToolName === "update_file") && result.startsWith("SUCCESS")) {
14654
14759
  const { path: filePath } = parseArgs(toolCall.args);
14655
14760
  if (filePath) {
14656
- const absPath = path21.resolve(process.cwd(), filePath);
14761
+ const absPath = path22.resolve(process.cwd(), filePath);
14657
14762
  openFileInEditor(absPath);
14658
14763
  }
14659
14764
  }
@@ -14916,9 +15021,9 @@ ${boxMid}`) };
14916
15021
  })() : String(err);
14917
15022
  ;
14918
15023
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
14919
- const agentErrDir = path21.join(LOGS_DIR, "agent");
14920
- if (!fs22.existsSync(agentErrDir)) fs22.mkdirSync(agentErrDir, { recursive: true });
14921
- fs22.appendFileSync(path21.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
15024
+ const agentErrDir = path22.join(LOGS_DIR, "agent");
15025
+ if (!fs23.existsSync(agentErrDir)) fs23.mkdirSync(agentErrDir, { recursive: true });
15026
+ fs23.appendFileSync(path22.join(agentErrDir, "error.log"), `ERROR [${date}]: ${errLog}
14922
15027
 
14923
15028
  ----------------------------------------------------------------------
14924
15029
 
@@ -14965,7 +15070,7 @@ ${recoveryText}`
14965
15070
  yield { type: "status", content: `Error Occured. Recovering Stream...` };
14966
15071
  } else {
14967
15072
  throw new Error(`Stream collapsed too many times. (Failed to resolve ${MAX_RETRIES} times)
14968
- Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
15073
+ Error Log can be found in ${path22.join(LOGS_DIR, "agent", "error.log")}`);
14969
15074
  }
14970
15075
  } else {
14971
15076
  if (retryCount <= MAX_RETRIES) {
@@ -14983,7 +15088,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
14983
15088
  yield { type: "status", content: `Trying to reach ${modelName}` };
14984
15089
  } else {
14985
15090
  throw new Error(`Model ${modelName} cannot be reached. (Failed ${MAX_RETRIES} times)
14986
- Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
15091
+ Error Log can be found in ${path22.join(LOGS_DIR, "agent", "error.log")}`);
14987
15092
  }
14988
15093
  }
14989
15094
  }
@@ -15015,6 +15120,7 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
15015
15120
  const cleanedTurnText = contextSafeReplace(turnText, /(\[\s*(turn\s*:)?\s*(continue|finish)\s*\]|\[\[END\]\])/gi, "").trim();
15016
15121
  let isActuallyFinished = (hasFinish || toolResults.length === 0) && !isThinkingLoop && !isStutteringLoop && !isGeneralLoop;
15017
15122
  isActuallyFinished = toolResults.length === 0 ? isActuallyFinished : false;
15123
+ isActuallyFinished = detectedAnyToolCalls || wasToolCalledInLastLoop ? false : isActuallyFinished;
15018
15124
  if (turnText && turnText.trim().endsWith('")]') && toolResults.length === 0) {
15019
15125
  isActuallyFinished = false;
15020
15126
  }
@@ -15042,13 +15148,20 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
15042
15148
  modifiedHistory.push({ role: "agent", text: nextAgentMsg });
15043
15149
  if (toolResults.length > 0 || anyToolExecutedInThisTurn) {
15044
15150
  if (toolResults.length > 0) {
15045
- const combinedText = toolResults.map((tr) => tr.text).join("\n\n");
15151
+ let combinedText = toolResults.map((tr) => tr.text).join("\n\n");
15152
+ const toolActionableText = turnText.replace(/(?:<(think|thought|thoughts)>|\[(think|thought|thoughts)\])[\s\S]*?(?:<\/(think|thought|thoughts)>|\[\/(think|thought|thoughts)\]|$)/gi, "");
15153
+ const attemptedToolsCount = (toolActionableText.match(/\[tool:functions/g) || []).length;
15154
+ if (toolResults.length < attemptedToolsCount) {
15155
+ combinedText += `
15156
+
15157
+ [SYSTEM] Only ${toolResults.length} out of ${attemptedToolsCount} attempted tool calls were executed. Verify proper syntax compliance & try failed calls again [/SYSTEM]`;
15158
+ }
15046
15159
  const binaryPart = toolResults.find((tr) => tr.binaryPart)?.binaryPart || null;
15047
15160
  modifiedHistory.push({ role: "user", text: combinedText, binaryPart });
15048
15161
  }
15049
15162
  } else {
15050
- if (wasToolCalledInLastLoop) {
15051
- modifiedHistory.push({ role: "user", text: `[SYSTEM] Failed to verify tool execution, MUST check if executed or failed. On failure try again [/SYSTEM]` });
15163
+ if (wasToolCalledInLastLoop || detectedAnyToolCalls) {
15164
+ modifiedHistory.push({ role: "user", text: `[SYSTEM] Failed to execute some tools. Verify proper syntax compliance & try again [/SYSTEM]` });
15052
15165
  } else {
15053
15166
  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 execution/output" : "If you have finished your task use [[END]]"}`} [/SYSTEM]` });
15054
15167
  }
@@ -15089,10 +15202,10 @@ Error Log can be found in ${path21.join(LOGS_DIR, "agent", "error.log")}`);
15089
15202
  }
15090
15203
  })() : String(err);
15091
15204
  const date = (/* @__PURE__ */ new Date()).toLocaleString();
15092
- const agentErrDir = path21.join(LOGS_DIR, "agent");
15205
+ const agentErrDir = path22.join(LOGS_DIR, "agent");
15093
15206
  yield { type: "text", content: `\u274C CRITICAL ERROR: ${errLog}` };
15094
- if (!fs22.existsSync(agentErrDir)) fs22.mkdirSync(agentErrDir, { recursive: true });
15095
- fs22.appendFileSync(path21.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
15207
+ if (!fs23.existsSync(agentErrDir)) fs23.mkdirSync(agentErrDir, { recursive: true });
15208
+ fs23.appendFileSync(path22.join(agentErrDir, "error.log"), `CRITICAL ERROR [${date}]: ${err}
15096
15209
 
15097
15210
  ----------------------------------------------------------------------
15098
15211
 
@@ -15234,20 +15347,20 @@ ${cleanResponse}
15234
15347
  } else if (normalizedToolName === "web_scrape" || normalizedToolName === "webscrape") {
15235
15348
  label = `\u2714 \x1B[95mScraped\x1B[0m`;
15236
15349
  } else if (normalizedToolName === "view_file" || normalizedToolName === "viewfile" || normalizedToolName === "readfile") {
15237
- const path23 = parseArgs(toolCall.args).path || "";
15238
- label = `\u2714 \x1B[95mRead File\x1B[0m: ${path23}`;
15350
+ const path24 = parseArgs(toolCall.args).path || "";
15351
+ label = `\u2714 \x1B[95mRead File\x1B[0m: ${path24}`;
15239
15352
  } else if (normalizedToolName === "list_files" || normalizedToolName === "read_folder" || normalizedToolName === "readfolder") {
15240
- const path23 = parseArgs(toolCall.args).path || "";
15241
- label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m: ${path23}`;
15353
+ const path24 = parseArgs(toolCall.args).path || "";
15354
+ label = `\u2714 \x1B[95mBrowsed Folder\x1B[0m: ${path24}`;
15242
15355
  } else if (normalizedToolName === "write_file" || normalizedToolName === "writefile") {
15243
- const path23 = parseArgs(toolCall.args).path || "";
15244
- label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path23}`;
15356
+ const path24 = parseArgs(toolCall.args).path || "";
15357
+ label = `\u2714 \x1B[95mFile Created\x1B[0m: ${path24}`;
15245
15358
  } else if (normalizedToolName === "update_file" || normalizedToolName === "updatefile" || normalizedToolName === "patchfile" || normalizedToolName === "patch_file" || normalizedToolName === "patchfile" || normalizedToolName === "updatefile") {
15246
- const path23 = parseArgs(toolCall.args).path || "";
15247
- label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path23}`;
15359
+ const path24 = parseArgs(toolCall.args).path || "";
15360
+ label = `\u2714 \x1B[95mFile Edited\x1B[0m: ${path24}`;
15248
15361
  } else if (normalizedToolName === "file_map" || normalizedToolName === "filemap") {
15249
- const path23 = parseArgs(toolCall.args).path || "";
15250
- label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path23}`;
15362
+ const path24 = parseArgs(toolCall.args).path || "";
15363
+ label = `\u2714 \x1B[95mIndexed\x1B[0m: ${path24}`;
15251
15364
  } else if (normalizedToolName === "await") {
15252
15365
  const { time } = parseArgs(toolCall.args);
15253
15366
  let sec = parseFloat(time) || 0;
@@ -16162,7 +16275,7 @@ var init_RevertModal = __esm({
16162
16275
  import puppeteer4 from "puppeteer";
16163
16276
  import { exec } from "child_process";
16164
16277
  import { promisify } from "util";
16165
- import fs23 from "fs";
16278
+ import fs24 from "fs";
16166
16279
  var execAsync, checkPuppeteerReady, installPuppeteerBrowser;
16167
16280
  var init_setup = __esm({
16168
16281
  "src/utils/setup.js"() {
@@ -16171,11 +16284,11 @@ var init_setup = __esm({
16171
16284
  checkPuppeteerReady = () => {
16172
16285
  try {
16173
16286
  const pptrConfig = getPuppeteerConfig();
16174
- if (pptrConfig.executablePath && fs23.existsSync(pptrConfig.executablePath)) {
16287
+ if (pptrConfig.executablePath && fs24.existsSync(pptrConfig.executablePath)) {
16175
16288
  return true;
16176
16289
  }
16177
16290
  const exePath = puppeteer4.executablePath();
16178
- const exists = exePath && fs23.existsSync(exePath);
16291
+ const exists = exePath && fs24.existsSync(exePath);
16179
16292
  if (exists) return true;
16180
16293
  } catch (e) {
16181
16294
  return false;
@@ -16262,10 +16375,10 @@ __export(app_exports, {
16262
16375
  import os5 from "os";
16263
16376
  import React16, { useState as useState15, useEffect as useEffect12, useRef as useRef4, useMemo as useMemo2 } from "react";
16264
16377
  import { Box as Box14, Text as Text16, useInput as useInput9, useStdout as useStdout2, Static } from "ink";
16265
- import fs24 from "fs-extra";
16266
- import path22 from "path";
16378
+ import fs25 from "fs-extra";
16379
+ import path23 from "path";
16267
16380
  import { exec as exec2 } from "child_process";
16268
- import { fileURLToPath as fileURLToPath2 } from "url";
16381
+ import { fileURLToPath as fileURLToPath3 } from "url";
16269
16382
  import TextInput4 from "ink-text-input";
16270
16383
  import SelectInput2 from "ink-select-input";
16271
16384
  import gradient2 from "gradient-string";
@@ -16572,8 +16685,8 @@ function App({ args = [] }) {
16572
16685
  const [setupStep, setSetupStep] = useState15(0);
16573
16686
  const [latestVer, setLatestVer] = useState15(null);
16574
16687
  const [showFullThinking, setShowFullThinking] = useState15(false);
16575
- const [activeModel, setActiveModel] = useState15("gemma-4-31b-it");
16576
- const [janitorModel, setJanitorModel] = useState15("gemma-4-26b-a4b-it");
16688
+ const [activeModel, setActiveModel] = useState15(getDefaultModel("Google", "Free") || "gemma-4-31b-it");
16689
+ const [janitorModel, setJanitorModel] = useState15(getFallbackValue("gemma_janitor_fallback_google") || "gemma-4-26b-a4b-it");
16577
16690
  const [isInitializing, setIsInitializing] = useState15(true);
16578
16691
  const [isAppFocused, setIsAppFocused] = useState15(true);
16579
16692
  const lastFocusEventTime = useRef4(0);
@@ -16583,10 +16696,10 @@ function App({ args = [] }) {
16583
16696
  const kbPath = getKeybindingsPath(ideName);
16584
16697
  if (!kbPath) return;
16585
16698
  try {
16586
- await fs24.ensureDir(path22.dirname(kbPath));
16699
+ await fs25.ensureDir(path23.dirname(kbPath));
16587
16700
  let bindings = [];
16588
- if (fs24.existsSync(kbPath)) {
16589
- const content = fs24.readFileSync(kbPath, "utf8").trim();
16701
+ if (fs25.existsSync(kbPath)) {
16702
+ const content = fs25.readFileSync(kbPath, "utf8").trim();
16590
16703
  if (content) {
16591
16704
  try {
16592
16705
  bindings = parseJsonc(content);
@@ -16606,7 +16719,7 @@ function App({ args = [] }) {
16606
16719
  },
16607
16720
  "when": "terminalFocus"
16608
16721
  });
16609
- fs24.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
16722
+ fs25.writeFileSync(kbPath, JSON.stringify(bindings, null, 4), "utf8");
16610
16723
  cachedShortcut = "Shift + Enter";
16611
16724
  setMessages((prev) => {
16612
16725
  setCompletedIndex(prev.length + 1);
@@ -16727,37 +16840,14 @@ function App({ args = [] }) {
16727
16840
  if (isThirdRender.current) {
16728
16841
  return;
16729
16842
  }
16730
- const s = emojiSpace(2);
16731
- let defaultModel = "";
16732
- let modelDisplayName = "";
16733
- if (apiTier === "Free") {
16734
- if (aiProvider === "Google") {
16735
- defaultModel = "gemma-4-31b-it";
16736
- modelDisplayName = "Gemma 4 (Free default)";
16737
- } else if (aiProvider === "DeepSeek") {
16738
- defaultModel = "deepseek-v4-flash";
16739
- modelDisplayName = "DeepSeek Flash (Free default)";
16740
- } else if (aiProvider === "NVIDIA") {
16741
- defaultModel = "deepseek-ai/deepseek-v4-flash";
16742
- modelDisplayName = "DeepSeek V4 Flash (NVIDIA)";
16743
- } else {
16744
- defaultModel = "google/gemma-4-31b-it:free";
16745
- modelDisplayName = "Gemma 4 (Free default)";
16746
- }
16747
- } else {
16748
- if (aiProvider === "Google") {
16749
- defaultModel = "gemini-3-flash-preview";
16750
- modelDisplayName = "Gemini 3 Flash";
16751
- } else if (aiProvider === "DeepSeek") {
16752
- defaultModel = "deepseek-v4-flash";
16753
- modelDisplayName = "DeepSeek Flash";
16754
- } else if (aiProvider === "NVIDIA") {
16755
- defaultModel = "deepseek-ai/deepseek-v4-flash";
16756
- modelDisplayName = "DeepSeek V4 Flash (NVIDIA)";
16757
- } else {
16758
- defaultModel = "deepseek/deepseek-v4-flash";
16759
- modelDisplayName = "DeepSeek Flash";
16760
- }
16843
+ const defaultModel = getDefaultModel(aiProvider, apiTier);
16844
+ let modelDisplayName = defaultModel;
16845
+ if (defaultModel.includes("gemma")) {
16846
+ modelDisplayName = "Gemma";
16847
+ } else if (defaultModel.includes("deepseek")) {
16848
+ modelDisplayName = "DeepSeek Flash";
16849
+ } else if (defaultModel.includes("gemini")) {
16850
+ modelDisplayName = "Gemini Flash";
16761
16851
  }
16762
16852
  setActiveModel(defaultModel);
16763
16853
  saveSettings({ apiTier, activeModel: defaultModel });
@@ -17230,11 +17320,39 @@ function App({ args = [] }) {
17230
17320
  }
17231
17321
  if (suggestions.length > 0 && activeView === "chat") {
17232
17322
  if (key.upArrow) {
17233
- setSelectedIndex((prev) => prev > 0 ? prev - 1 : suggestions.length - 1);
17323
+ setSelectedIndex((prev) => {
17324
+ let nextIdx = prev > 0 ? prev - 1 : suggestions.length - 1;
17325
+ let loops = 0;
17326
+ while (nextIdx !== prev && loops < suggestions.length) {
17327
+ const sug = suggestions[nextIdx];
17328
+ const cmdName = sug?.cmd || sug || "";
17329
+ if (typeof cmdName === "string" && cmdName.trimStart().startsWith("---")) {
17330
+ nextIdx = nextIdx > 0 ? nextIdx - 1 : suggestions.length - 1;
17331
+ loops++;
17332
+ } else {
17333
+ break;
17334
+ }
17335
+ }
17336
+ return nextIdx;
17337
+ });
17234
17338
  return;
17235
17339
  }
17236
17340
  if (key.downArrow) {
17237
- setSelectedIndex((prev) => prev < suggestions.length - 1 ? prev + 1 : 0);
17341
+ setSelectedIndex((prev) => {
17342
+ let nextIdx = prev < suggestions.length - 1 ? prev + 1 : 0;
17343
+ let loops = 0;
17344
+ while (nextIdx !== prev && loops < suggestions.length) {
17345
+ const sug = suggestions[nextIdx];
17346
+ const cmdName = sug?.cmd || sug || "";
17347
+ if (typeof cmdName === "string" && cmdName.trimStart().startsWith("---")) {
17348
+ nextIdx = nextIdx < suggestions.length - 1 ? nextIdx + 1 : 0;
17349
+ loops++;
17350
+ } else {
17351
+ break;
17352
+ }
17353
+ }
17354
+ return nextIdx;
17355
+ });
17238
17356
  return;
17239
17357
  }
17240
17358
  if (key.return) {
@@ -17285,7 +17403,7 @@ function App({ args = [] }) {
17285
17403
  useEffect12(() => {
17286
17404
  async function init() {
17287
17405
  try {
17288
- const pkg = JSON.parse(fs24.readFileSync(path22.join(process.cwd(), "package.json"), "utf8"));
17406
+ const pkg = JSON.parse(fs25.readFileSync(path23.join(process.cwd(), "package.json"), "utf8"));
17289
17407
  initBridge(versionFluxflow || pkg.version || "2.0.0");
17290
17408
  } catch (e) {
17291
17409
  initBridge("2.0.0");
@@ -17305,6 +17423,7 @@ function App({ args = [] }) {
17305
17423
  return [...prev, { id: "setup-done-" + Date.now(), role: "system", text: "[SYSTEM] All dependencies installed successfully.", isMeta: true }];
17306
17424
  });
17307
17425
  }
17426
+ await loadRemoteModelConfig();
17308
17427
  const saved = await loadSettings();
17309
17428
  originalAllowExternalAccessRef.current = saved.systemSettings?.allowExternalAccess ?? false;
17310
17429
  originalMemoryRef.current = saved.systemSettings?.memory ?? true;
@@ -17326,28 +17445,7 @@ function App({ args = [] }) {
17326
17445
  if (parsedArgs.model) {
17327
17446
  setActiveModel(parsedArgs.model);
17328
17447
  } else if (parsedArgs.provider) {
17329
- let defaultModel = "";
17330
- if (currentTier === "Free") {
17331
- if (startupProvider === "Google") {
17332
- defaultModel = "gemma-4-31b-it";
17333
- } else if (startupProvider === "DeepSeek") {
17334
- defaultModel = "deepseek-v4-flash";
17335
- } else if (startupProvider === "OpenRouter") {
17336
- defaultModel = "google/gemma-4-31b-it:free";
17337
- } else if (startupProvider === "NVIDIA") {
17338
- defaultModel = "deepseek-ai/deepseek-v4-flash";
17339
- }
17340
- } else {
17341
- if (startupProvider === "Google") {
17342
- defaultModel = "gemini-3-flash-preview";
17343
- } else if (startupProvider === "DeepSeek") {
17344
- defaultModel = "deepseek-v4-flash";
17345
- } else if (startupProvider === "OpenRouter") {
17346
- defaultModel = "deepseek/deepseek-v4-flash";
17347
- } else if (startupProvider === "NVIDIA") {
17348
- defaultModel = "deepseek-ai/deepseek-v4-flash";
17349
- }
17350
- }
17448
+ const defaultModel = getDefaultModel(startupProvider, currentTier);
17351
17449
  setActiveModel(defaultModel);
17352
17450
  } else {
17353
17451
  setActiveModel(saved.activeModel);
@@ -17408,7 +17506,7 @@ function App({ args = [] }) {
17408
17506
  if (!parsedArgs.playground) {
17409
17507
  deleteChat(PLAYGROUND_CHAT_ID).catch(() => {
17410
17508
  });
17411
- fs24.remove(path22.join(DATA_DIR, "playground")).catch(() => {
17509
+ fs25.remove(path23.join(DATA_DIR, "playground")).catch(() => {
17412
17510
  });
17413
17511
  }
17414
17512
  performVersionCheck(false, freshSettings);
@@ -17442,9 +17540,9 @@ function App({ args = [] }) {
17442
17540
  }
17443
17541
  }
17444
17542
  if (parsedArgs.playground) {
17445
- const playgroundDir = path22.join(DATA_DIR, "playground");
17543
+ const playgroundDir = path23.join(DATA_DIR, "playground");
17446
17544
  try {
17447
- fs24.ensureDirSync(playgroundDir);
17545
+ fs25.ensureDirSync(playgroundDir);
17448
17546
  process.chdir(playgroundDir);
17449
17547
  } catch (e) {
17450
17548
  }
@@ -17485,8 +17583,8 @@ function App({ args = [] }) {
17485
17583
  if (kbPath) {
17486
17584
  try {
17487
17585
  let bindings = [];
17488
- if (fs24.existsSync(kbPath)) {
17489
- const content = fs24.readFileSync(kbPath, "utf8").trim();
17586
+ if (fs25.existsSync(kbPath)) {
17587
+ const content = fs25.readFileSync(kbPath, "utf8").trim();
17490
17588
  if (content) {
17491
17589
  bindings = parseJsonc(content);
17492
17590
  }
@@ -17650,211 +17748,7 @@ function App({ args = [] }) {
17650
17748
  {
17651
17749
  cmd: "/model",
17652
17750
  desc: "Select Agent Model",
17653
- subs: aiProvider === "OpenRouter" ? apiTier === "Free" ? [
17654
- {
17655
- cmd: "google/gemma-4-31b-it:free",
17656
- desc: "Multimodal"
17657
- },
17658
- {
17659
- cmd: "moonshotai/kimi-k2.6:free",
17660
- desc: "Multimodal"
17661
- },
17662
- {
17663
- cmd: "qwen/qwen3-coder:free",
17664
- desc: "Text Only"
17665
- },
17666
- {
17667
- cmd: "z-ai/glm-4.5-air:free",
17668
- desc: "Text Only"
17669
- }
17670
- ] : [
17671
- {
17672
- cmd: "google/gemini-3.5-flash",
17673
- desc: "Multimodal"
17674
- },
17675
- {
17676
- cmd: "qwen/qwen3.7-plus",
17677
- desc: "Multimodal"
17678
- },
17679
- {
17680
- cmd: "minimax/minimax-m3",
17681
- desc: "Multimodal"
17682
- },
17683
- {
17684
- cmd: "anthropic/claude-sonnet-4.5",
17685
- desc: "Multimodal"
17686
- },
17687
- {
17688
- cmd: "anthropic/claude-opus-4.6",
17689
- desc: "Multimodal"
17690
- },
17691
- {
17692
- cmd: "anthropic/claude-opus-4.8",
17693
- desc: "Multimodal"
17694
- },
17695
- {
17696
- cmd: "deepseek/deepseek-v4-pro",
17697
- desc: "Text Only"
17698
- },
17699
- {
17700
- cmd: "deepseek/deepseek-v4-flash",
17701
- desc: "Text Only"
17702
- },
17703
- {
17704
- cmd: "xiaomi/mimo-v2.5-pro",
17705
- desc: "Text Only"
17706
- },
17707
- {
17708
- cmd: "z-ai/glm-5",
17709
- desc: "Text Only"
17710
- },
17711
- {
17712
- cmd: "openai/gpt-5.2-codex",
17713
- desc: "Multimodal"
17714
- },
17715
- {
17716
- cmd: "openai/gpt-5.2-pro",
17717
- desc: "Multimodal"
17718
- },
17719
- {
17720
- cmd: "openai/gpt-5.5-pro",
17721
- desc: "Multimodal"
17722
- },
17723
- {
17724
- cmd: "moonshotai/kimi-k2.6",
17725
- desc: "Multimodal"
17726
- }
17727
- ] : aiProvider === "DeepSeek" ? [
17728
- {
17729
- cmd: "deepseek-v4-flash",
17730
- desc: "Fast & Efficient (Text Only)"
17731
- },
17732
- {
17733
- cmd: "deepseek-v4-pro",
17734
- desc: "High-Intelligence Reasoning (Text Only)"
17735
- }
17736
- ] : aiProvider === "NVIDIA" ? [
17737
- // --- Kimi (Moonshot AI) ---
17738
- {
17739
- cmd: "moonshotai/kimi-k2.7",
17740
- desc: "Multimodal"
17741
- },
17742
- // --- DeepSeek Family ---
17743
- {
17744
- cmd: "deepseek-ai/deepseek-v4-flash",
17745
- desc: "Text Only"
17746
- },
17747
- {
17748
- cmd: "deepseek-ai/deepseek-v4-pro",
17749
- desc: "Text Only"
17750
- },
17751
- // --- StepFun ---
17752
- {
17753
- cmd: "stepfun-ai/step-3.7-flash",
17754
- desc: "Multimodal"
17755
- },
17756
- // --- Gemma Family (Google) ---
17757
- {
17758
- cmd: "google/gemma-4-31b-it",
17759
- desc: "Multimodal"
17760
- },
17761
- {
17762
- cmd: "google/diffusiongemma-26b-a4b-it",
17763
- desc: "Mega Fast [Experimental]"
17764
- },
17765
- // --- Mistral ---
17766
- {
17767
- cmd: "mistralai/mistral-medium-3.5-128b",
17768
- desc: "Multimodal"
17769
- },
17770
- // --- GPT Open Source Series (OpenAI) ---
17771
- {
17772
- cmd: "openai/gpt-oss-20b",
17773
- desc: "Text Only"
17774
- },
17775
- {
17776
- cmd: "openai/gpt-oss-120b",
17777
- desc: "Text Only"
17778
- },
17779
- // --- GLM (Zhipu AI) ---
17780
- {
17781
- cmd: "z-ai/glm-5.2",
17782
- desc: "Text Only"
17783
- },
17784
- // --- MiniMax Family ---
17785
- {
17786
- cmd: "minimaxai/minimax-m2.7",
17787
- desc: "Text Only"
17788
- },
17789
- {
17790
- cmd: "minimaxai/minimax-m3",
17791
- desc: "Text Only"
17792
- },
17793
- // QWEN
17794
- {
17795
- cmd: "qwen/qwen3.5-397b-a17b",
17796
- desc: "Multimodal"
17797
- },
17798
- // NVIDIA NEMOTRON
17799
- {
17800
- cmd: "nvidia/nemotron-3-ultra-550b-a55b",
17801
- desc: "Text Only [EXPERIMENTAL]"
17802
- }
17803
- ] : apiTier === "Free" ? [
17804
- {
17805
- cmd: "gemma-4-26b-a4b-it",
17806
- desc: "Standard & Faster (Multimodal)"
17807
- },
17808
- {
17809
- cmd: "gemma-4-31b-it",
17810
- desc: "Standard Default (Multimodal)"
17811
- },
17812
- {
17813
- cmd: "gemini-2.5-flash-lite",
17814
- desc: "Fast & Cheap (Multimodal) [Limited Free Quota]"
17815
- },
17816
- {
17817
- cmd: "gemini-2.5-flash",
17818
- desc: "Fast & Reliable (Multimodal) [Limited Free Quota]"
17819
- },
17820
- {
17821
- cmd: "gemini-3-flash-preview",
17822
- desc: "Fast & Lightweight (Multimodal) [Limited Free Quota]"
17823
- },
17824
- {
17825
- cmd: "gemini-3.5-flash",
17826
- desc: "Flash Latest (Multimodal) [Limited Free Quota] Instability Issues"
17827
- }
17828
- ] : [
17829
- {
17830
- cmd: "gemini-2.5-flash-lite",
17831
- desc: "Fast & Cheap (Multimodal)"
17832
- },
17833
- {
17834
- cmd: "gemini-2.5-flash",
17835
- desc: "Fast & Reliable (Multimodal)"
17836
- },
17837
- {
17838
- cmd: "gemini-2.5-pro",
17839
- desc: "Last gen Pro reasoning (Multimodal)"
17840
- },
17841
- {
17842
- cmd: "gemini-3.1-flash-lite",
17843
- desc: "Ultra-Fast & Lite (Multimodal)"
17844
- },
17845
- {
17846
- cmd: "gemini-3-flash-preview",
17847
- desc: "Default, Fast & Lightweight (Multimodal)"
17848
- },
17849
- {
17850
- cmd: "gemini-3.5-flash",
17851
- desc: "Flash Latest (Multimodal) [Instability Issues]"
17852
- },
17853
- {
17854
- cmd: "gemini-3.1-pro-preview",
17855
- desc: "Pro Reasoning (Multimodal)"
17856
- }
17857
- ]
17751
+ subs: getModels(aiProvider, apiTier)
17858
17752
  },
17859
17753
  {
17860
17754
  cmd: "/mode",
@@ -18015,22 +17909,22 @@ ${cleanText}`, color: "magenta" }];
18015
17909
  });
18016
17910
  break;
18017
17911
  }
18018
- const src = path22.join(DATA_DIR, "playground");
18019
- const dest = path22.join(parsedArgs.originalCwd, "playground-export");
17912
+ const src = path23.join(DATA_DIR, "playground");
17913
+ const dest = path23.join(parsedArgs.originalCwd, "playground-export");
18020
17914
  const moveFiles = async () => {
18021
17915
  try {
18022
17916
  setMessages((prev) => {
18023
17917
  setCompletedIndex(prev.length + 1);
18024
17918
  return [...prev, { id: Date.now(), role: "system", text: `[PLAYGROUND] Exporting playground content to ${dest}`, isMeta: true }];
18025
17919
  });
18026
- await fs24.ensureDir(dest);
17920
+ await fs25.ensureDir(dest);
18027
17921
  const excludeDirs = ["node_modules", ".git", ".venv", "venv", "env", ".next", "dist", "build", ".cache"];
18028
- await fs24.copy(src, dest, {
17922
+ await fs25.copy(src, dest, {
18029
17923
  overwrite: true,
18030
17924
  filter: (srcPath) => {
18031
- const relative = path22.relative(src, srcPath);
17925
+ const relative = path23.relative(src, srcPath);
18032
17926
  if (!relative) return true;
18033
- const parts2 = relative.split(path22.sep);
17927
+ const parts2 = relative.split(path23.sep);
18034
17928
  return !parts2.some((part) => excludeDirs.includes(part));
18035
17929
  }
18036
17930
  });
@@ -18090,7 +17984,7 @@ ${cleanText}`, color: "magenta" }];
18090
17984
  }
18091
17985
  }
18092
17986
  setTimeout(() => {
18093
- fs24.emptyDir(path22.join(DATA_DIR, "playground")).catch((err) => {
17987
+ fs25.emptyDir(path23.join(DATA_DIR, "playground")).catch((err) => {
18094
17988
  setMessages((prev) => {
18095
17989
  const newMsgs = [...prev, {
18096
17990
  id: "playground-" + Date.now(),
@@ -18334,17 +18228,19 @@ ${cleanText}`, color: "magenta" }];
18334
18228
  case "/model": {
18335
18229
  if (parts[1]) {
18336
18230
  const mod = parts.slice(1).join(" ");
18337
- if (mod === "gemma-4-31b-it" && apiTier !== "Free" && aiProvider === "Google") {
18231
+ const freeDefault = getDefaultModel("Google", "Free");
18232
+ const paidDefault = getDefaultModel("Google", "Paid");
18233
+ if (mod === freeDefault && apiTier !== "Free" && aiProvider === "Google") {
18338
18234
  setMessages((prev) => {
18339
18235
  setCompletedIndex(prev.length + 1);
18340
18236
  return [...prev, {
18341
18237
  id: Date.now(),
18342
18238
  role: "system",
18343
- text: `**[ACCESS DENIED]** Gemma is restricted to the Free API tier. Automatically switching you to **Gemini 3 Flash Preview** for optimal performance.`,
18239
+ text: `**[ACCESS DENIED]** ${freeDefault} is restricted to the Free API tier. Automatically switching you to **${paidDefault}** for optimal performance.`,
18344
18240
  isMeta: true
18345
18241
  }];
18346
18242
  });
18347
- setActiveModel("gemini-3-flash-preview");
18243
+ setActiveModel(paidDefault);
18348
18244
  } else {
18349
18245
  setActiveModel(mod);
18350
18246
  const s2 = emojiSpace(2);
@@ -18393,7 +18289,7 @@ ${cleanText}`, color: "magenta" }];
18393
18289
  }
18394
18290
  case "/export": {
18395
18291
  const exportFile = `export-fluxflow-${chatId}.txt`;
18396
- const exportPath = path22.join(process.cwd(), exportFile);
18292
+ const exportPath = path23.join(process.cwd(), exportFile);
18397
18293
  const exportLines = [];
18398
18294
  let insideAgentBlock = false;
18399
18295
  for (let i = 0; i < messages.length; i++) {
@@ -18445,7 +18341,7 @@ ${cleanText}`, color: "magenta" }];
18445
18341
  }
18446
18342
  const fileContent = exportLines.join("\n");
18447
18343
  try {
18448
- fs24.writeFileSync(exportPath, fileContent, "utf8");
18344
+ fs25.writeFileSync(exportPath, fileContent, "utf8");
18449
18345
  setMessages((prev) => {
18450
18346
  setCompletedIndex(prev.length + 1);
18451
18347
  return [...prev, {
@@ -18492,12 +18388,12 @@ ${list || "No saved chats found."}`, isMeta: true }];
18492
18388
  setCompletedIndex(prev.length + 1);
18493
18389
  return [...prev, { id: Date.now(), role: "system", text: "[NUCLEAR] Initiating reset...", isMeta: true }];
18494
18390
  });
18495
- if (fs24.existsSync(LOGS_DIR)) fs24.removeSync(LOGS_DIR);
18496
- if (fs24.existsSync(SECRET_DIR)) fs24.removeSync(SECRET_DIR);
18497
- if (fs24.existsSync(SETTINGS_FILE)) fs24.removeSync(SETTINGS_FILE);
18391
+ if (fs25.existsSync(LOGS_DIR)) fs25.removeSync(LOGS_DIR);
18392
+ if (fs25.existsSync(SECRET_DIR)) fs25.removeSync(SECRET_DIR);
18393
+ if (fs25.existsSync(SETTINGS_FILE)) fs25.removeSync(SETTINGS_FILE);
18498
18394
  try {
18499
- const items = fs24.readdirSync(FLUXFLOW_DIR);
18500
- if (items.length === 0) fs24.removeSync(FLUXFLOW_DIR);
18395
+ const items = fs25.readdirSync(FLUXFLOW_DIR);
18396
+ if (items.length === 0) fs25.removeSync(FLUXFLOW_DIR);
18501
18397
  } catch (e) {
18502
18398
  }
18503
18399
  setTimeout(() => {
@@ -18619,15 +18515,15 @@ ${list || "No saved chats found."}`, isMeta: true }];
18619
18515
  # SKILLS & WORKFLOWS
18620
18516
  - [Define custom step-by-step recipes for this project here]
18621
18517
  `;
18622
- const filePath = path22.join(process.cwd(), "FluxFlow.md");
18623
- if (fs24.pathExistsSync(filePath)) {
18518
+ const filePath = path23.join(process.cwd(), "FluxFlow.md");
18519
+ if (fs25.pathExistsSync(filePath)) {
18624
18520
  setMessages((prev) => {
18625
18521
  setCompletedIndex(prev.length + 1);
18626
18522
  return [...prev, { id: "init-err-" + Date.now(), role: "system", text: "ERROR: FluxFlow.md already exists in this directory.", isMeta: true }];
18627
18523
  });
18628
18524
  } else {
18629
18525
  try {
18630
- fs24.writeFileSync(filePath, template);
18526
+ fs25.writeFileSync(filePath, template);
18631
18527
  setMessages((prev) => {
18632
18528
  setCompletedIndex(prev.length + 1);
18633
18529
  return [...prev, { id: "init-ok-" + Date.now(), role: "system", text: "[SUCCESS] FluxFlow.md has been initialized. You can now customize it for this project.", isMeta: true }];
@@ -19523,7 +19419,17 @@ Selection: ${val}`,
19523
19419
  return [];
19524
19420
  }, [input, isFilePickerDismissed]);
19525
19421
  useEffect12(() => {
19526
- setSelectedIndex(0);
19422
+ let startIdx = 0;
19423
+ while (startIdx < suggestions.length) {
19424
+ const sug = suggestions[startIdx];
19425
+ const cmdName = sug?.cmd || sug || "";
19426
+ if (typeof cmdName === "string" && cmdName.trimStart().startsWith("---")) {
19427
+ startIdx++;
19428
+ } else {
19429
+ break;
19430
+ }
19431
+ }
19432
+ setSelectedIndex(startIdx < suggestions.length ? startIdx : 0);
19527
19433
  }, [suggestions]);
19528
19434
  const [suggestionVisibleCount, setSuggestionVisibleCount] = useState15(0);
19529
19435
  const prevSuggestionsLenRef = useRef4(0);
@@ -19699,16 +19605,9 @@ Selection: ${val}`,
19699
19605
  setAiProvider(selectedProvider);
19700
19606
  setApiKey(key);
19701
19607
  initAI(key, { aiProvider: selectedProvider, onIDEApproval: resetPendingApproval });
19702
- let defaultModel = "gemma-4-31b-it";
19703
- if (selectedProvider === "OpenRouter") {
19704
- defaultModel = "google/gemma-4-31b-it:free";
19705
- } else if (selectedProvider === "DeepSeek") {
19706
- defaultModel = "deepseek-v4-flash";
19707
- } else if (selectedProvider === "NVIDIA") {
19708
- defaultModel = "deepseek-ai/deepseek-v4-flash";
19709
- }
19710
- setActiveModel(defaultModel);
19711
19608
  const targetTier = (quotas.providerTiers || {})[selectedProvider] || "Free";
19609
+ const defaultModel = getDefaultModel(selectedProvider, targetTier);
19610
+ setActiveModel(defaultModel);
19712
19611
  setApiTier(targetTier);
19713
19612
  saveSettings({ aiProvider: selectedProvider, activeModel: defaultModel, apiTier: targetTier, quotas });
19714
19613
  setMessages((prev) => [
@@ -20027,16 +19926,9 @@ Selection: ${val}`,
20027
19926
  setAiProvider(prov);
20028
19927
  setApiKey(keyInput);
20029
19928
  initAI(keyInput, { aiProvider: prov, onIDEApproval: resetPendingApproval });
20030
- let defaultModel = "gemma-4-31b-it";
20031
- if (prov === "OpenRouter") {
20032
- defaultModel = "google/gemma-4-31b-it:free";
20033
- } else if (prov === "DeepSeek") {
20034
- defaultModel = "deepseek-v4-flash";
20035
- } else if (prov === "NVIDIA") {
20036
- defaultModel = "moonshotai/kimi-k2.6";
20037
- }
20038
- setActiveModel(defaultModel);
20039
19929
  const targetTier = (quotas.providerTiers || {})[prov] || "Free";
19930
+ const defaultModel = getDefaultModel(prov, targetTier);
19931
+ setActiveModel(defaultModel);
20040
19932
  setApiTier(targetTier);
20041
19933
  newSettings.aiProvider = prov;
20042
19934
  newSettings.activeModel = defaultModel;
@@ -20598,7 +20490,19 @@ Selection: ${val}`,
20598
20490
  )), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Press ESC to go back to provider selection)")))), /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, setupStep === 0 ? "(Use arrows to select and Enter to confirm)" : "(Press Enter to confirm and initialize)"))) : renderActiveView(), confirmExit && /* @__PURE__ */ React16.createElement(Box14, { borderStyle: "round", borderColor: "white", paddingX: 2, marginY: 0, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, "\u{1F534} EXIT CONFIRMATION: "), /* @__PURE__ */ React16.createElement(Text16, { color: "white" }, "Press "), /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, "CTRL + C"), /* @__PURE__ */ React16.createElement(Text16, { color: "white" }, " again to exit (", exitCountdown, "s). Press "), /* @__PURE__ */ React16.createElement(Text16, { color: "gray", bold: true }, "ESC"), /* @__PURE__ */ React16.createElement(Text16, { color: "white" }, " to cancel.")), suggestions.length > 0 && (() => {
20599
20491
  const windowSize = 5;
20600
20492
  let startIdx = suggestionOffsetRef.current;
20601
- if (selectedIndex < startIdx) {
20493
+ let firstSelectableIndex = 0;
20494
+ while (firstSelectableIndex < suggestions.length) {
20495
+ const sug = suggestions[firstSelectableIndex];
20496
+ const cmdName = sug?.cmd || sug || "";
20497
+ if (typeof cmdName === "string" && cmdName.trimStart().startsWith("---")) {
20498
+ firstSelectableIndex++;
20499
+ } else {
20500
+ break;
20501
+ }
20502
+ }
20503
+ if (selectedIndex <= firstSelectableIndex) {
20504
+ startIdx = 0;
20505
+ } else if (selectedIndex < startIdx) {
20602
20506
  startIdx = selectedIndex;
20603
20507
  } else if (selectedIndex >= startIdx + windowSize) {
20604
20508
  startIdx = selectedIndex - windowSize + 1;
@@ -20614,7 +20518,7 @@ Selection: ${val}`,
20614
20518
  width: "100%",
20615
20519
  marginBottom: 1
20616
20520
  },
20617
- /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use '#Lstart-Lend' to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20521
+ /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginBottom: 0, justifyContent: "space-between", width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true }, suggestions[0]?.cmd?.startsWith("@") ? "FILE SUGGESTIONS" : "COMMAND SUGGESTIONS"), suggestions[0]?.cmd?.startsWith("@") ? /* @__PURE__ */ React16.createElement(Text16, { color: "gray", italic: true }, "(Use \\'#Lstart-Lend\\' to specify line numbers)") : input.startsWith("/model") && apiTier === "Free" ? (() => {
20618
20522
  let url = "https://aistudio.google.com/billing";
20619
20523
  let label = "billing";
20620
20524
  if (aiProvider === "DeepSeek") {
@@ -20632,7 +20536,8 @@ Selection: ${val}`,
20632
20536
  visible.slice(0, suggestionVisibleCount).map((s, i) => {
20633
20537
  const actualIdx = startIdx + i;
20634
20538
  const isActive = actualIdx === selectedIndex;
20635
- const isGemmaDisabled = s.cmd === "gemma-4-31b-it" && apiTier !== "Free";
20539
+ const isDivider = typeof s.cmd === "string" && s.cmd.trimStart().startsWith("---");
20540
+ const isGemmaDisabled = s.cmd === getDefaultModel("Google", "Free") && apiTier !== "Free";
20636
20541
  return /* @__PURE__ */ React16.createElement(
20637
20542
  Box14,
20638
20543
  {
@@ -20641,18 +20546,18 @@ Selection: ${val}`,
20641
20546
  backgroundColor: isActive ? "#2a2a2a" : void 0,
20642
20547
  paddingX: 1
20643
20548
  },
20644
- /* @__PURE__ */ React16.createElement(Box14, { width: 3 }, /* @__PURE__ */ React16.createElement(Text16, { color: isActive ? "white" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
20549
+ /* @__PURE__ */ React16.createElement(Box14, { width: 3 }, /* @__PURE__ */ React16.createElement(Text16, { color: isActive ? "#B8BDC9" : "gray", bold: isActive }, isActive ? " \u276F" : " ")),
20645
20550
  /* @__PURE__ */ React16.createElement(Box14, { width: 55 }, /* @__PURE__ */ React16.createElement(
20646
20551
  Text16,
20647
20552
  {
20648
- color: isGemmaDisabled ? "gray" : isActive ? "white" : "grey",
20649
- bold: isActive
20553
+ color: isDivider ? "#D0CCD8" : isGemmaDisabled ? "gray" : isActive ? "white" : "grey",
20554
+ bold: false
20650
20555
  },
20651
20556
  s.cmd?.startsWith("@[") && s.cmd?.endsWith("]") ? (() => {
20652
20557
  const pathPart = s.cmd.slice(2, -1);
20653
20558
  const parts = pathPart.split(/[/\\]/);
20654
20559
  return parts[parts.length - 1];
20655
- })() : s.cmd
20560
+ })() : s.cmd && s.cmd.includes("/") ? s.cmd.split("/").pop() : s.cmd
20656
20561
  )),
20657
20562
  /* @__PURE__ */ React16.createElement(Box14, { flexGrow: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: `${!isActive ? "gray" : "white"}`, italic: true }, s.desc))
20658
20563
  );
@@ -20709,6 +20614,7 @@ var init_app = __esm({
20709
20614
  init_witty_phrases();
20710
20615
  init_RevertModal();
20711
20616
  init_usage();
20617
+ init_model_config();
20712
20618
  init_TerminalBox();
20713
20619
  init_arg_parser();
20714
20620
  init_paths();
@@ -20768,11 +20674,11 @@ var init_app = __esm({
20768
20674
  if (process.platform === "win32") {
20769
20675
  const appData = process.env.APPDATA;
20770
20676
  if (!appData) return null;
20771
- return path22.join(appData, dirName, "User", "keybindings.json");
20677
+ return path23.join(appData, dirName, "User", "keybindings.json");
20772
20678
  } else if (process.platform === "darwin") {
20773
- return path22.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
20679
+ return path23.join(home, "Library", "Application Support", dirName, "User", "keybindings.json");
20774
20680
  } else {
20775
- return path22.join(home, ".config", dirName, "User", "keybindings.json");
20681
+ return path23.join(home, ".config", dirName, "User", "keybindings.json");
20776
20682
  }
20777
20683
  };
20778
20684
  parseJsonc = (content) => {
@@ -20816,8 +20722,8 @@ var init_app = __esm({
20816
20722
  SESSION_START_TIME = Date.now();
20817
20723
  CHANGELOG_URL = "https://fluxflow-cli.onrender.com/changelog";
20818
20724
  DOCS_URL = "https://fluxflow-cli.onrender.com/";
20819
- packageJsonPath = path22.join(path22.dirname(fileURLToPath2(import.meta.url)), "../package.json");
20820
- packageJson = JSON.parse(fs24.readFileSync(packageJsonPath, "utf8"));
20725
+ packageJsonPath = path23.join(path23.dirname(fileURLToPath3(import.meta.url)), "../package.json");
20726
+ packageJson = JSON.parse(fs25.readFileSync(packageJsonPath, "utf8"));
20821
20727
  versionFluxflow = packageJson.version;
20822
20728
  updatedOn = packageJson.date || "2026-05-20";
20823
20729
  ResolutionModal = ({ data, onResolve, onEdit }) => /* @__PURE__ */ React16.createElement(Box14, { flexDirection: "column", borderStyle: "round", borderColor: "grey", padding: 0, width: "100%" }, /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "white", bold: true, underline: true }, data.startsWith("/btw") ? "QUESTION" : "STEERING HINT", " RESOLUTION")), /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, null, "The agent already finished the task before your ", data.startsWith("/btw") ? "question" : "hint", " was consumed.")), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 1, backgroundColor: "#222", paddingX: 2, width: "100%" }, /* @__PURE__ */ React16.createElement(Text16, { italic: true, color: "gray" }, '"', data.replace("/btw", "").trim(), '"')), /* @__PURE__ */ React16.createElement(Box14, { paddingX: 1, marginTop: 1 }, /* @__PURE__ */ React16.createElement(Text16, { color: "grey" }, "How would you like to proceed?")), /* @__PURE__ */ React16.createElement(Box14, { marginTop: 0 }, /* @__PURE__ */ React16.createElement(
@@ -20914,20 +20820,20 @@ var init_app = __esm({
20914
20820
  const scan = (currentDir) => {
20915
20821
  if (fileList.length >= 2e3) return;
20916
20822
  try {
20917
- const files = fs24.readdirSync(currentDir);
20823
+ const files = fs25.readdirSync(currentDir);
20918
20824
  for (const file of files) {
20919
20825
  if (fileList.length >= 2e3) return;
20920
20826
  if (["node_modules", ".git", ".gemini", "dist", "build", ".next", ".cache", "out"].includes(file)) {
20921
20827
  continue;
20922
20828
  }
20923
- const filePath = path22.join(currentDir, file);
20924
- const stat = fs24.statSync(filePath);
20829
+ const filePath = path23.join(currentDir, file);
20830
+ const stat = fs25.statSync(filePath);
20925
20831
  if (stat.isDirectory()) {
20926
20832
  scan(filePath);
20927
20833
  } else {
20928
20834
  fileList.push({
20929
20835
  name: flattenString(file),
20930
- relativePath: flattenString(path22.relative(process.cwd(), filePath))
20836
+ relativePath: flattenString(path23.relative(process.cwd(), filePath))
20931
20837
  });
20932
20838
  }
20933
20839
  }
@@ -21031,7 +20937,7 @@ var init_app = __esm({
21031
20937
 
21032
20938
  // src/cli.jsx
21033
20939
  import { spawn as spawn3 } from "child_process";
21034
- import { fileURLToPath as fileURLToPath3 } from "url";
20940
+ import { fileURLToPath as fileURLToPath4 } from "url";
21035
20941
  import os6 from "os";
21036
20942
  var totalSystemRamBytes = os6.totalmem();
21037
20943
  var totalSystemRamMB = totalSystemRamBytes / (1024 * 1024);
@@ -21048,7 +20954,7 @@ if (!isNaN(_allocValue) && _allocValue < 64) {
21048
20954
  }
21049
20955
  var _maxAllowed = Math.floor(totalSystemRamMB * 0.75);
21050
20956
  var HEAP_LIMIT = !isNaN(_allocValue) && _allocValue > 0 ? Math.min(_allocValue, _maxAllowed) : Math.max(1536, Math.min(32768, calculatedLimit));
21051
- var isBundled = fileURLToPath3(import.meta.url).endsWith(".js");
20957
+ var isBundled = fileURLToPath4(import.meta.url).endsWith(".js");
21052
20958
  if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-size"))) {
21053
20959
  if (!Number.isNaN(_allocValue)) {
21054
20960
  console.log(`
@@ -21059,7 +20965,7 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
21059
20965
  `--max-old-space-size=${HEAP_LIMIT}`,
21060
20966
  `--expose-gc`,
21061
20967
  `--max-semi-space-size=1`,
21062
- fileURLToPath3(import.meta.url),
20968
+ fileURLToPath4(import.meta.url),
21063
20969
  ...process.argv.slice(2)
21064
20970
  ], { stdio: "inherit" });
21065
20971
  cp.on("exit", (code) => process.exit(code || 0));
@@ -21070,11 +20976,11 @@ if (isBundled && !process.execArgv.some((arg) => arg.includes("max-old-space-siz
21070
20976
  const isVersion = args.includes("--version") || args.includes("-v");
21071
20977
  const isUpdate = args[0] === "--update";
21072
20978
  if (isVersion || isHelp || isHelpCommands || isUpdate) {
21073
- const fs25 = await import("fs");
21074
- const path23 = await import("path");
21075
- const { fileURLToPath: fileURLToPath4 } = await import("url");
21076
- const packageJsonPath2 = path23.join(path23.dirname(fileURLToPath4(import.meta.url)), "../package.json");
21077
- const packageJson2 = JSON.parse(fs25.readFileSync(packageJsonPath2, "utf8"));
20979
+ const fs26 = await import("fs");
20980
+ const path24 = await import("path");
20981
+ const { fileURLToPath: fileURLToPath5 } = await import("url");
20982
+ const packageJsonPath2 = path24.join(path24.dirname(fileURLToPath5(import.meta.url)), "../package.json");
20983
+ const packageJson2 = JSON.parse(fs26.readFileSync(packageJsonPath2, "utf8"));
21078
20984
  const versionFluxflow2 = packageJson2.version;
21079
20985
  if (isVersion) {
21080
20986
  console.log(`v${versionFluxflow2}`);